From: Good Guy Date: Mon, 21 Nov 2016 03:46:36 +0000 (-0700) Subject: add xvid/flv formats, add motion plugin varients + save file, fix build bug X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=1e154071bd323f756625f8172ef67133a561450a;p=goodguy%2Fhistory.git add xvid/flv formats, add motion plugin varients + save file, fix build bug --- diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 16c6409b..9b468bf4 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -1949,7 +1949,7 @@ int FFMPEG::encode_activate() (ret=avio_open(&fmt_ctx->pb, fmt_ctx->filename, AVIO_FLAG_WRITE)) < 0 ) { ff_err(ret, "FFMPEG::encode_activate: err opening : %s\n", fmt_ctx->filename); - return 1; + return -1; } AVDictionary *fopts = 0; @@ -1961,7 +1961,7 @@ int FFMPEG::encode_activate() if( ret < 0 ) { ff_err(ret, "FFMPEG::encode_activate: write header failed %s\n", fmt_ctx->filename); - return 1; + return -1; } encoding = 1; } diff --git a/cinelerra-5.1/ffmpeg/audio/f4v.dfl b/cinelerra-5.1/ffmpeg/audio/f4v.dfl new file mode 100644 index 00000000..8b64dbf5 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/audio/f4v.dfl @@ -0,0 +1 @@ +mp3.f4v diff --git a/cinelerra-5.1/ffmpeg/audio/flv.dfl b/cinelerra-5.1/ffmpeg/audio/flv.dfl new file mode 100644 index 00000000..da751b7c --- /dev/null +++ b/cinelerra-5.1/ffmpeg/audio/flv.dfl @@ -0,0 +1 @@ +mp3.flv diff --git a/cinelerra-5.1/ffmpeg/audio/mp3.f4v b/cinelerra-5.1/ffmpeg/audio/mp3.f4v new file mode 100644 index 00000000..f524cf0f --- /dev/null +++ b/cinelerra-5.1/ffmpeg/audio/mp3.f4v @@ -0,0 +1 @@ +f4v libmp3lame diff --git a/cinelerra-5.1/ffmpeg/audio/mp3.flv b/cinelerra-5.1/ffmpeg/audio/mp3.flv new file mode 100644 index 00000000..05d193c4 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/audio/mp3.flv @@ -0,0 +1,2 @@ +flv libmp3lame +# sample rate must be: 44100 or 22050 or 11025 diff --git a/cinelerra-5.1/ffmpeg/encode.opts b/cinelerra-5.1/ffmpeg/encode.opts index 73021c58..79301da3 100644 --- a/cinelerra-5.1/ffmpeg/encode.opts +++ b/cinelerra-5.1/ffmpeg/encode.opts @@ -1,3 +1,4 @@ # apply at init encode +loglevel=error threads=auto side_data_only_packets=1 diff --git a/cinelerra-5.1/ffmpeg/flv.dfl b/cinelerra-5.1/ffmpeg/flv.dfl new file mode 100644 index 00000000..da751b7c --- /dev/null +++ b/cinelerra-5.1/ffmpeg/flv.dfl @@ -0,0 +1 @@ +mp3.flv diff --git a/cinelerra-5.1/ffmpeg/video/avi.xvid b/cinelerra-5.1/ffmpeg/video/avi.xvid new file mode 100644 index 00000000..acb78bf7 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/video/avi.xvid @@ -0,0 +1,2 @@ +avi mpeg4 +vtag xvid diff --git a/cinelerra-5.1/ffmpeg/video/f4v.dfl b/cinelerra-5.1/ffmpeg/video/f4v.dfl new file mode 100644 index 00000000..c1d2d642 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/video/f4v.dfl @@ -0,0 +1 @@ +h264.f4v diff --git a/cinelerra-5.1/ffmpeg/video/flv.dfl b/cinelerra-5.1/ffmpeg/video/flv.dfl new file mode 100644 index 00000000..85a67a71 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/video/flv.dfl @@ -0,0 +1 @@ +flv.flv diff --git a/cinelerra-5.1/ffmpeg/video/flv.flv b/cinelerra-5.1/ffmpeg/video/flv.flv new file mode 100644 index 00000000..46af192a --- /dev/null +++ b/cinelerra-5.1/ffmpeg/video/flv.flv @@ -0,0 +1 @@ +flv flv diff --git a/cinelerra-5.1/ffmpeg/video/h264.f4v b/cinelerra-5.1/ffmpeg/video/h264.f4v new file mode 100644 index 00000000..664351d7 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/video/h264.f4v @@ -0,0 +1,5 @@ +f4v libx264 +profile=baseline +level=3.0 +preset=medium +x264opts keyint=25:min-keyint=4:qpmin=3:qpmax=33:qp_step=4:merange=8 diff --git a/cinelerra-5.1/ffmpeg/video/xvid.dfl b/cinelerra-5.1/ffmpeg/video/xvid.dfl new file mode 100644 index 00000000..da30cb20 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/video/xvid.dfl @@ -0,0 +1 @@ +avi.xvid diff --git a/cinelerra-5.1/plugin_defs b/cinelerra-5.1/plugin_defs index 3dbe03f1..d8fdbbd0 100644 --- a/cinelerra-5.1/plugin_defs +++ b/cinelerra-5.1/plugin_defs @@ -37,9 +37,9 @@ plugin_dirs += video_tools video_tools := blur decimate delayvideo denoisemjpeg denoisevideo downsample \ fieldframe flash framefield freezeframe greycstoration interpolatepixels \ interpolatevideo invertvideo linearblur loopvideo motion2 motionblur \ - motion overlay radialblur reframe reframert reroute reversevideo \ - seltempavg sharpen spectrogram svg titler timeavg timefront unsharp \ - videoscope wave zoomblur + motion motion-cv motion-hv overlay radialblur reframe reframert reroute \ + reversevideo seltempavg sharpen spectrogram svg titler timeavg timefront \ + unsharp videoscope wave zoomblur plugin_dirs += blending blending := chromakeyhsv chromakey diffkey diff --git a/cinelerra-5.1/plugins/Makefile b/cinelerra-5.1/plugins/Makefile index c233f06c..5bac9134 100644 --- a/cinelerra-5.1/plugins/Makefile +++ b/cinelerra-5.1/plugins/Makefile @@ -78,6 +78,8 @@ DIRS = \ loopaudio \ loopvideo \ motion \ + motion-cv \ + motion-hv \ motion2point \ motionblur \ normalize \ diff --git a/cinelerra-5.1/plugins/interpolatevideo/Makefile b/cinelerra-5.1/plugins/interpolatevideo/Makefile index 98baa20f..3b50feb2 100644 --- a/cinelerra-5.1/plugins/interpolatevideo/Makefile +++ b/cinelerra-5.1/plugins/interpolatevideo/Makefile @@ -3,7 +3,9 @@ include ../../plugin_defs OBJS = $(OBJDIR)/interpolatevideo.o \ $(OBJDIR)/interpolatewindow.o \ $(OBJDIR)/opticflow.o \ - $(OBJDIR)/motionscan.o + $(OBJDIR)/motionscan-hv.o + +CFLAGS += -DMotionScan=MotionHVScan PLUGIN = interpolatevideo @@ -13,4 +15,4 @@ include ../../plugin_config $(OBJDIR)/interpolatevideo.o: interpolatevideo.C $(OBJDIR)/interpolatewindow.o: interpolatewindow.C $(OBJDIR)/opticflow.o: opticflow.C -$(OBJDIR)/motionscan.o: motionscan.C motionscan.h +$(OBJDIR)/motionscan-hv.o: motionscan-hv.C motionscan-hv.h diff --git a/cinelerra-5.1/plugins/interpolatevideo/interpolatevideo.C b/cinelerra-5.1/plugins/interpolatevideo/interpolatevideo.C index 017be8d5..9e553ac3 100644 --- a/cinelerra-5.1/plugins/interpolatevideo/interpolatevideo.C +++ b/cinelerra-5.1/plugins/interpolatevideo/interpolatevideo.C @@ -24,7 +24,7 @@ #include "interpolatevideo.h" #include "interpolatewindow.h" #include "language.h" -#include "motionscan.h" +#include "motionscan-hv.h" #include "opticflow.h" #include "transportque.inc" #include diff --git a/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.C b/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.C new file mode 120000 index 00000000..898c188d --- /dev/null +++ b/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.C @@ -0,0 +1 @@ +../motion-hv/motionscan-hv.C \ No newline at end of file diff --git a/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.h b/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.h new file mode 120000 index 00000000..d5eb987c --- /dev/null +++ b/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.h @@ -0,0 +1 @@ +../motion-hv/motionscan-hv.h \ No newline at end of file diff --git a/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.inc b/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.inc new file mode 120000 index 00000000..4c59354a --- /dev/null +++ b/cinelerra-5.1/plugins/interpolatevideo/motionscan-hv.inc @@ -0,0 +1 @@ +../motion-hv/motionscan-hv.inc \ No newline at end of file diff --git a/cinelerra-5.1/plugins/interpolatevideo/motionscan.C b/cinelerra-5.1/plugins/interpolatevideo/motionscan.C deleted file mode 120000 index 4ac14722..00000000 --- a/cinelerra-5.1/plugins/interpolatevideo/motionscan.C +++ /dev/null @@ -1 +0,0 @@ -../motion/motionscan.C \ No newline at end of file diff --git a/cinelerra-5.1/plugins/interpolatevideo/motionscan.h b/cinelerra-5.1/plugins/interpolatevideo/motionscan.h deleted file mode 120000 index 9461913f..00000000 --- a/cinelerra-5.1/plugins/interpolatevideo/motionscan.h +++ /dev/null @@ -1 +0,0 @@ -../motion/motionscan.h \ No newline at end of file diff --git a/cinelerra-5.1/plugins/interpolatevideo/motionscan.inc b/cinelerra-5.1/plugins/interpolatevideo/motionscan.inc deleted file mode 120000 index e4b8d557..00000000 --- a/cinelerra-5.1/plugins/interpolatevideo/motionscan.inc +++ /dev/null @@ -1 +0,0 @@ -../motion/motionscan.inc \ No newline at end of file diff --git a/cinelerra-5.1/plugins/interpolatevideo/opticflow.C b/cinelerra-5.1/plugins/interpolatevideo/opticflow.C index bce991b0..9f94d6be 100644 --- a/cinelerra-5.1/plugins/interpolatevideo/opticflow.C +++ b/cinelerra-5.1/plugins/interpolatevideo/opticflow.C @@ -24,7 +24,7 @@ #include "clip.h" #include "interpolatevideo.h" -#include "motionscan.h" +#include "motionscan-hv.h" #include "opticflow.h" #include diff --git a/cinelerra-5.1/plugins/interpolatevideo/opticflow.h b/cinelerra-5.1/plugins/interpolatevideo/opticflow.h index bbea19df..6e611fc5 100644 --- a/cinelerra-5.1/plugins/interpolatevideo/opticflow.h +++ b/cinelerra-5.1/plugins/interpolatevideo/opticflow.h @@ -24,7 +24,7 @@ #include "interpolatevideo.inc" #include "loadbalance.h" -#include "motionscan.inc" +#include "motionscan-hv.inc" #include "opticflow.inc" // Need a 2nd table if a large number of packages diff --git a/cinelerra-5.1/plugins/motion-cv/.deps/motion.Plo b/cinelerra-5.1/plugins/motion-cv/.deps/motion.Plo new file mode 100644 index 00000000..22e9e747 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/.deps/motion.Plo @@ -0,0 +1,691 @@ +motion.lo: motion.C /usr/include/stdc-predef.h ../../cinelerra/affine.h \ + ../../cinelerra/affine.inc ../../cinelerra/loadbalance.h \ + ../../guicast/condition.inc ../../guicast/mutex.inc \ + ../../guicast/thread.h /usr/include/pthread.h /usr/include/features.h \ + /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \ + /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \ + /usr/include/endian.h /usr/include/bits/endian.h \ + /usr/include/bits/byteswap.h /usr/include/bits/types.h \ + /usr/include/bits/typesizes.h /usr/include/bits/byteswap-16.h \ + /usr/include/sched.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h \ + /usr/include/time.h /usr/include/bits/sched.h /usr/include/bits/time.h \ + /usr/include/bits/timex.h /usr/include/xlocale.h \ + /usr/include/bits/pthreadtypes.h /usr/include/bits/setjmp.h \ + ../../guicast/vframe.inc ../../guicast/bcdisplayinfo.h \ + /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdarg.h \ + /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \ + /usr/include/stdlib.h /usr/include/bits/waitflags.h \ + /usr/include/bits/waitstatus.h /usr/include/sys/types.h \ + /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h \ + /usr/include/alloca.h /usr/include/bits/stdlib-float.h \ + /usr/include/X11/Xlib.h /usr/include/X11/X.h \ + /usr/include/X11/Xfuncproto.h /usr/include/X11/Xosdefs.h \ + ../../guicast/clip.h ../../guicast/bchash.h \ + ../../guicast/bcwindowbase.inc ../../guicast/hashcache.inc \ + ../../guicast/units.h ../../guicast/sizes.h /usr/include/math.h \ + /usr/include/bits/math-vector.h /usr/include/bits/libm-simd-decl-stubs.h \ + /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \ + /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \ + /usr/include/bits/nan.h /usr/include/bits/mathdef.h \ + /usr/include/bits/mathcalls.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdint.h \ + /usr/include/stdint.h /usr/include/bits/wchar.h \ + ../../cinelerra/filexml.h ../../guicast/sizes.h \ + ../../cinelerra/keyframe.h ../../cinelerra/auto.h \ + ../../cinelerra/auto.inc ../../cinelerra/edl.inc ../../guicast/guicast.h \ + ../../guicast/bcbar.h ../../guicast/bcsubwindow.h \ + ../../guicast/arraylist.h ../../guicast/bcwindowbase.h ../../config.h \ + ../../guicast/bcbar.inc ../../guicast/bcbitmap.inc \ + ../../guicast/bcbutton.inc ../../guicast/bccapture.inc \ + ../../guicast/bcclipboard.inc ../../guicast/bccmodels.inc \ + ../../guicast/bcdragwindow.inc ../../guicast/bcfilebox.inc \ + ../../guicast/bclistbox.inc ../../guicast/bcmenubar.inc \ + ../../guicast/bcmeter.inc ../../guicast/bcpan.inc \ + ../../guicast/bcpbuffer.inc ../../guicast/bcpixmap.inc \ + ../../guicast/bcpopup.inc ../../guicast/bcpopupmenu.inc \ + ../../guicast/bcpot.inc ../../guicast/bcprogress.inc \ + ../../guicast/bcrelocatablewidget.h ../../guicast/bcrepeater.inc \ + ../../guicast/bcresources.inc ../../guicast/bcscrollbar.inc \ + ../../guicast/bcslider.inc ../../guicast/bcsubwindow.inc \ + ../../guicast/bcsynchronous.inc ../../guicast/bctextbox.inc \ + ../../guicast/bctimer.inc ../../guicast/bctitle.inc \ + ../../guicast/bctoggle.inc ../../guicast/bctumble.inc \ + ../../guicast/bcwidgetgrid.inc ../../guicast/bcwindow.inc \ + ../../guicast/bcwindowevents.inc ../../guicast/condition.inc \ + ../../guicast/bchash.inc ../../guicast/linklist.h \ + ../../guicast/mutex.inc ../../guicast/vframe.inc \ + /usr/include/X11/Xatom.h /usr/include/X11/Xft/Xft.h \ + /usr/include/freetype2/ft2build.h \ + /usr/include/freetype2/config/ftheader.h \ + /usr/include/freetype2/freetype.h \ + /usr/include/freetype2/config/ftconfig.h \ + /usr/include/freetype2/config/ftconfig-64.h \ + /usr/include/freetype2/config/ftoption.h \ + /usr/include/freetype2/config/ftstdlib.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/limits.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/bits/posix1_lim.h \ + /usr/include/bits/local_lim.h /usr/include/linux/limits.h \ + /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \ + /usr/include/string.h /usr/include/setjmp.h \ + /usr/include/freetype2/fttypes.h /usr/include/freetype2/ftsystem.h \ + /usr/include/freetype2/ftimage.h /usr/include/freetype2/fterrors.h \ + /usr/include/freetype2/ftmoderr.h /usr/include/freetype2/fterrdef.h \ + /usr/include/fontconfig/fontconfig.h /usr/include/sys/stat.h \ + /usr/include/bits/stat.h /usr/include/X11/extensions/Xrender.h \ + /usr/include/X11/Xutil.h /usr/include/X11/keysym.h \ + /usr/include/X11/keysymdef.h /usr/include/X11/extensions/render.h \ + /usr/include/X11/Xdefs.h /usr/include/X11/Xft/XftCompat.h \ + /usr/include/X11/cursorfont.h /usr/include/X11/extensions/xf86vmode.h \ + /usr/include/X11/Xmd.h /usr/include/X11/extensions/xf86vm.h \ + /usr/include/GL/glx.h /usr/include/GL/gl.h /usr/include/GL/glext.h \ + /usr/include/inttypes.h /usr/include/GL/glxext.h \ + ../../guicast/bcbitmap.h /usr/include/sys/ipc.h \ + /usr/include/bits/ipctypes.h /usr/include/bits/ipc.h \ + /usr/include/sys/shm.h /usr/include/bits/shm.h \ + /usr/include/X11/extensions/XShm.h /usr/include/X11/extensions/shm.h \ + /usr/include/X11/extensions/Xvlib.h /usr/include/X11/extensions/Xv.h \ + ../../guicast/colors.h ../../guicast/bcbutton.h \ + ../../guicast/bcclipboard.h ../../guicast/thread.h \ + ../../guicast/bcdragwindow.h ../../guicast/bcpopup.h \ + ../../guicast/bclistboxitem.h ../../guicast/vframe.h \ + ../../guicast/bctexture.inc ../../quicktime/colormodels.h \ + ../../guicast/bccmodels.h ../../guicast/bcpan.h \ + ../../guicast/rotateframe.inc ../../guicast/bcfilebox.h \ + ../../guicast/bcdelete.inc ../../guicast/bclistboxitem.inc \ + ../../guicast/bcnewfolder.inc ../../guicast/bctextbox.h \ + ../../guicast/bclistbox.h ../../guicast/bcscrollbar.h \ + ../../guicast/bctoggle.h ../../guicast/fonts.h ../../guicast/bctumble.h \ + ../../guicast/bcwindow.h ../../guicast/filesystem.inc \ + ../../guicast/bcmenu.h ../../guicast/bcmenuitem.inc \ + ../../guicast/bcmenupopup.inc ../../guicast/bcmenubar.h \ + ../../guicast/bcmenu.inc ../../guicast/bcmenuitem.h \ + ../../guicast/bcmenupopup.h ../../guicast/bcmeter.h \ + ../../guicast/bcpopupmenu.h ../../guicast/bcpot.h \ + ../../guicast/bcpixmap.h ../../guicast/bcprogress.h \ + ../../guicast/bcrecentlist.h ../../guicast/bcresources.h \ + ../../guicast/bcdisplayinfo.inc ../../guicast/bcfontentry.inc \ + ../../guicast/bcsignals.inc ../../guicast/bcslider.h \ + ../../guicast/bcsynchronous.h ../../guicast/bctexture.h \ + ../../guicast/bctheme.h ../../guicast/bctitle.h ../../guicast/bctimer.h \ + /usr/include/sys/time.h ../../guicast/error.h ../../guicast/debug.h \ + ../../cinelerra/filexml.inc ../../cinelerra/autos.inc \ + ../../cinelerra/keyframes.inc ../../cinelerra/messages.inc \ + ../../guicast/language.h /usr/include/libintl.h motion.h \ + ../../cinelerra/affine.inc ../../guicast/bchash.inc \ + ../../cinelerra/filexml.inc ../../cinelerra/keyframe.inc \ + ../../cinelerra/loadbalance.h motionwindow.inc \ + ../../cinelerra/overlayframe.inc ../../cinelerra/pluginvclient.h \ + ../../cinelerra/maxbuffers.h ../../cinelerra/pluginclient.h \ + ../../guicast/arraylist.h ../../guicast/condition.h \ + ../../cinelerra/edlsession.inc ../../cinelerra/keyframe.h \ + ../../cinelerra/mainprogress.inc ../../cinelerra/plugincommands.h \ + ../../cinelerra/pluginserver.inc ../../cinelerra/theme.inc \ + ../../guicast/vframe.h ../../guicast/rotateframe.inc motionwindow.h \ + motion.inc ../../cinelerra/pluginwindow.h ../../guicast/bcwindow.h \ + ../../guicast/mutex.h ../../cinelerra/overlayframe.h \ + ../../cinelerra/overlayframe.inc picon_png.h ../../guicast/rotateframe.h \ + ../../cinelerra/transportque.h ../../cinelerra/canvas.inc \ + ../../cinelerra/preferences.inc ../../cinelerra/transportque.inc \ + /usr/include/errno.h /usr/include/bits/errno.h \ + /usr/include/linux/errno.h /usr/include/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/unistd.h /usr/include/bits/posix_opt.h \ + /usr/include/bits/environments.h /usr/include/bits/confname.h \ + /usr/include/getopt.h + +/usr/include/stdc-predef.h: + +../../cinelerra/affine.h: + +../../cinelerra/affine.inc: + +../../cinelerra/loadbalance.h: + +../../guicast/condition.inc: + +../../guicast/mutex.inc: + +../../guicast/thread.h: + +/usr/include/pthread.h: + +/usr/include/features.h: + +/usr/include/sys/cdefs.h: + +/usr/include/bits/wordsize.h: + +/usr/include/gnu/stubs.h: + +/usr/include/gnu/stubs-64.h: + +/usr/include/endian.h: + +/usr/include/bits/endian.h: + +/usr/include/bits/byteswap.h: + +/usr/include/bits/types.h: + +/usr/include/bits/typesizes.h: + +/usr/include/bits/byteswap-16.h: + +/usr/include/sched.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h: + +/usr/include/time.h: + +/usr/include/bits/sched.h: + +/usr/include/bits/time.h: + +/usr/include/bits/timex.h: + +/usr/include/xlocale.h: + +/usr/include/bits/pthreadtypes.h: + +/usr/include/bits/setjmp.h: + +../../guicast/vframe.inc: + +../../guicast/bcdisplayinfo.h: + +/usr/include/stdio.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdarg.h: + +/usr/include/bits/stdio_lim.h: + +/usr/include/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/bits/waitflags.h: + +/usr/include/bits/waitstatus.h: + +/usr/include/sys/types.h: + +/usr/include/sys/select.h: + +/usr/include/bits/select.h: + +/usr/include/bits/sigset.h: + +/usr/include/sys/sysmacros.h: + +/usr/include/alloca.h: + +/usr/include/bits/stdlib-float.h: + +/usr/include/X11/Xlib.h: + +/usr/include/X11/X.h: + +/usr/include/X11/Xfuncproto.h: + +/usr/include/X11/Xosdefs.h: + +../../guicast/clip.h: + +../../guicast/bchash.h: + +../../guicast/bcwindowbase.inc: + +../../guicast/hashcache.inc: + +../../guicast/units.h: + +../../guicast/sizes.h: + +/usr/include/math.h: + +/usr/include/bits/math-vector.h: + +/usr/include/bits/libm-simd-decl-stubs.h: + +/usr/include/bits/huge_val.h: + +/usr/include/bits/huge_valf.h: + +/usr/include/bits/huge_vall.h: + +/usr/include/bits/inf.h: + +/usr/include/bits/nan.h: + +/usr/include/bits/mathdef.h: + +/usr/include/bits/mathcalls.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdint.h: + +/usr/include/stdint.h: + +/usr/include/bits/wchar.h: + +../../cinelerra/filexml.h: + +../../guicast/sizes.h: + +../../cinelerra/keyframe.h: + +../../cinelerra/auto.h: + +../../cinelerra/auto.inc: + +../../cinelerra/edl.inc: + +../../guicast/guicast.h: + +../../guicast/bcbar.h: + +../../guicast/bcsubwindow.h: + +../../guicast/arraylist.h: + +../../guicast/bcwindowbase.h: + +../../config.h: + +../../guicast/bcbar.inc: + +../../guicast/bcbitmap.inc: + +../../guicast/bcbutton.inc: + +../../guicast/bccapture.inc: + +../../guicast/bcclipboard.inc: + +../../guicast/bccmodels.inc: + +../../guicast/bcdragwindow.inc: + +../../guicast/bcfilebox.inc: + +../../guicast/bclistbox.inc: + +../../guicast/bcmenubar.inc: + +../../guicast/bcmeter.inc: + +../../guicast/bcpan.inc: + +../../guicast/bcpbuffer.inc: + +../../guicast/bcpixmap.inc: + +../../guicast/bcpopup.inc: + +../../guicast/bcpopupmenu.inc: + +../../guicast/bcpot.inc: + +../../guicast/bcprogress.inc: + +../../guicast/bcrelocatablewidget.h: + +../../guicast/bcrepeater.inc: + +../../guicast/bcresources.inc: + +../../guicast/bcscrollbar.inc: + +../../guicast/bcslider.inc: + +../../guicast/bcsubwindow.inc: + +../../guicast/bcsynchronous.inc: + +../../guicast/bctextbox.inc: + +../../guicast/bctimer.inc: + +../../guicast/bctitle.inc: + +../../guicast/bctoggle.inc: + +../../guicast/bctumble.inc: + +../../guicast/bcwidgetgrid.inc: + +../../guicast/bcwindow.inc: + +../../guicast/bcwindowevents.inc: + +../../guicast/condition.inc: + +../../guicast/bchash.inc: + +../../guicast/linklist.h: + +../../guicast/mutex.inc: + +../../guicast/vframe.inc: + +/usr/include/X11/Xatom.h: + +/usr/include/X11/Xft/Xft.h: + +/usr/include/freetype2/ft2build.h: + +/usr/include/freetype2/config/ftheader.h: + +/usr/include/freetype2/freetype.h: + +/usr/include/freetype2/config/ftconfig.h: + +/usr/include/freetype2/config/ftconfig-64.h: + +/usr/include/freetype2/config/ftoption.h: + +/usr/include/freetype2/config/ftstdlib.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/limits.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/bits/posix1_lim.h: + +/usr/include/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/bits/posix2_lim.h: + +/usr/include/bits/xopen_lim.h: + +/usr/include/string.h: + +/usr/include/setjmp.h: + +/usr/include/freetype2/fttypes.h: + +/usr/include/freetype2/ftsystem.h: + +/usr/include/freetype2/ftimage.h: + +/usr/include/freetype2/fterrors.h: + +/usr/include/freetype2/ftmoderr.h: + +/usr/include/freetype2/fterrdef.h: + +/usr/include/fontconfig/fontconfig.h: + +/usr/include/sys/stat.h: + +/usr/include/bits/stat.h: + +/usr/include/X11/extensions/Xrender.h: + +/usr/include/X11/Xutil.h: + +/usr/include/X11/keysym.h: + +/usr/include/X11/keysymdef.h: + +/usr/include/X11/extensions/render.h: + +/usr/include/X11/Xdefs.h: + +/usr/include/X11/Xft/XftCompat.h: + +/usr/include/X11/cursorfont.h: + +/usr/include/X11/extensions/xf86vmode.h: + +/usr/include/X11/Xmd.h: + +/usr/include/X11/extensions/xf86vm.h: + +/usr/include/GL/glx.h: + +/usr/include/GL/gl.h: + +/usr/include/GL/glext.h: + +/usr/include/inttypes.h: + +/usr/include/GL/glxext.h: + +../../guicast/bcbitmap.h: + +/usr/include/sys/ipc.h: + +/usr/include/bits/ipctypes.h: + +/usr/include/bits/ipc.h: + +/usr/include/sys/shm.h: + +/usr/include/bits/shm.h: + +/usr/include/X11/extensions/XShm.h: + +/usr/include/X11/extensions/shm.h: + +/usr/include/X11/extensions/Xvlib.h: + +/usr/include/X11/extensions/Xv.h: + +../../guicast/colors.h: + +../../guicast/bcbutton.h: + +../../guicast/bcclipboard.h: + +../../guicast/thread.h: + +../../guicast/bcdragwindow.h: + +../../guicast/bcpopup.h: + +../../guicast/bclistboxitem.h: + +../../guicast/vframe.h: + +../../guicast/bctexture.inc: + +../../quicktime/colormodels.h: + +../../guicast/bccmodels.h: + +../../guicast/bcpan.h: + +../../guicast/rotateframe.inc: + +../../guicast/bcfilebox.h: + +../../guicast/bcdelete.inc: + +../../guicast/bclistboxitem.inc: + +../../guicast/bcnewfolder.inc: + +../../guicast/bctextbox.h: + +../../guicast/bclistbox.h: + +../../guicast/bcscrollbar.h: + +../../guicast/bctoggle.h: + +../../guicast/fonts.h: + +../../guicast/bctumble.h: + +../../guicast/bcwindow.h: + +../../guicast/filesystem.inc: + +../../guicast/bcmenu.h: + +../../guicast/bcmenuitem.inc: + +../../guicast/bcmenupopup.inc: + +../../guicast/bcmenubar.h: + +../../guicast/bcmenu.inc: + +../../guicast/bcmenuitem.h: + +../../guicast/bcmenupopup.h: + +../../guicast/bcmeter.h: + +../../guicast/bcpopupmenu.h: + +../../guicast/bcpot.h: + +../../guicast/bcpixmap.h: + +../../guicast/bcprogress.h: + +../../guicast/bcrecentlist.h: + +../../guicast/bcresources.h: + +../../guicast/bcdisplayinfo.inc: + +../../guicast/bcfontentry.inc: + +../../guicast/bcsignals.inc: + +../../guicast/bcslider.h: + +../../guicast/bcsynchronous.h: + +../../guicast/bctexture.h: + +../../guicast/bctheme.h: + +../../guicast/bctitle.h: + +../../guicast/bctimer.h: + +/usr/include/sys/time.h: + +../../guicast/error.h: + +../../guicast/debug.h: + +../../cinelerra/filexml.inc: + +../../cinelerra/autos.inc: + +../../cinelerra/keyframes.inc: + +../../cinelerra/messages.inc: + +../../guicast/language.h: + +/usr/include/libintl.h: + +motion.h: + +../../cinelerra/affine.inc: + +../../guicast/bchash.inc: + +../../cinelerra/filexml.inc: + +../../cinelerra/keyframe.inc: + +../../cinelerra/loadbalance.h: + +motionwindow.inc: + +../../cinelerra/overlayframe.inc: + +../../cinelerra/pluginvclient.h: + +../../cinelerra/maxbuffers.h: + +../../cinelerra/pluginclient.h: + +../../guicast/arraylist.h: + +../../guicast/condition.h: + +../../cinelerra/edlsession.inc: + +../../cinelerra/keyframe.h: + +../../cinelerra/mainprogress.inc: + +../../cinelerra/plugincommands.h: + +../../cinelerra/pluginserver.inc: + +../../cinelerra/theme.inc: + +../../guicast/vframe.h: + +../../guicast/rotateframe.inc: + +motionwindow.h: + +motion.inc: + +../../cinelerra/pluginwindow.h: + +../../guicast/bcwindow.h: + +../../guicast/mutex.h: + +../../cinelerra/overlayframe.h: + +../../cinelerra/overlayframe.inc: + +picon_png.h: + +../../guicast/rotateframe.h: + +../../cinelerra/transportque.h: + +../../cinelerra/canvas.inc: + +../../cinelerra/preferences.inc: + +../../cinelerra/transportque.inc: + +/usr/include/errno.h: + +/usr/include/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/unistd.h: + +/usr/include/bits/posix_opt.h: + +/usr/include/bits/environments.h: + +/usr/include/bits/confname.h: + +/usr/include/getopt.h: diff --git a/cinelerra-5.1/plugins/motion-cv/.deps/motionwindow.Plo b/cinelerra-5.1/plugins/motion-cv/.deps/motionwindow.Plo new file mode 100644 index 00000000..08a9f0a6 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/.deps/motionwindow.Plo @@ -0,0 +1,621 @@ +motionwindow.lo: motionwindow.C /usr/include/stdc-predef.h \ + ../../guicast/bcdisplayinfo.h /usr/include/stdio.h \ + /usr/include/features.h /usr/include/sys/cdefs.h \ + /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \ + /usr/include/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h \ + /usr/include/bits/types.h /usr/include/bits/typesizes.h \ + /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdarg.h \ + /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \ + /usr/include/stdlib.h /usr/include/bits/waitflags.h \ + /usr/include/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/bits/endian.h /usr/include/bits/byteswap.h \ + /usr/include/bits/byteswap-16.h /usr/include/xlocale.h \ + /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \ + /usr/include/bits/select.h /usr/include/bits/sigset.h \ + /usr/include/bits/time.h /usr/include/sys/sysmacros.h \ + /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/bits/stdlib-float.h /usr/include/X11/Xlib.h \ + /usr/include/X11/X.h /usr/include/X11/Xfuncproto.h \ + /usr/include/X11/Xosdefs.h ../../guicast/clip.h ../../guicast/language.h \ + /usr/include/libintl.h motion.h /usr/include/math.h \ + /usr/include/bits/math-vector.h /usr/include/bits/libm-simd-decl-stubs.h \ + /usr/include/bits/huge_val.h /usr/include/bits/huge_valf.h \ + /usr/include/bits/huge_vall.h /usr/include/bits/inf.h \ + /usr/include/bits/nan.h /usr/include/bits/mathdef.h \ + /usr/include/bits/mathcalls.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdint.h \ + /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/string.h \ + ../../cinelerra/affine.inc ../../guicast/bchash.inc \ + ../../cinelerra/filexml.inc ../../cinelerra/keyframe.inc \ + ../../cinelerra/loadbalance.h ../../guicast/condition.inc \ + ../../guicast/mutex.inc ../../guicast/thread.h /usr/include/pthread.h \ + /usr/include/sched.h /usr/include/bits/sched.h /usr/include/bits/timex.h \ + /usr/include/bits/setjmp.h motionwindow.inc \ + ../../cinelerra/overlayframe.inc ../../cinelerra/pluginvclient.h \ + ../../cinelerra/maxbuffers.h ../../cinelerra/pluginclient.h \ + ../../guicast/arraylist.h ../../guicast/condition.h \ + ../../cinelerra/edlsession.inc ../../cinelerra/keyframe.h \ + ../../cinelerra/auto.h ../../cinelerra/auto.inc ../../cinelerra/edl.inc \ + ../../guicast/guicast.h ../../guicast/bcbar.h \ + ../../guicast/bcsubwindow.h ../../guicast/arraylist.h \ + ../../guicast/bcwindowbase.h ../../config.h ../../guicast/bcbar.inc \ + ../../guicast/bcbitmap.inc ../../guicast/bcbutton.inc \ + ../../guicast/bccapture.inc ../../guicast/bcclipboard.inc \ + ../../guicast/bccmodels.inc ../../guicast/bcdragwindow.inc \ + ../../guicast/bcfilebox.inc ../../guicast/bclistbox.inc \ + ../../guicast/bcmenubar.inc ../../guicast/bcmeter.inc \ + ../../guicast/bcpan.inc ../../guicast/bcpbuffer.inc \ + ../../guicast/bcpixmap.inc ../../guicast/bcpopup.inc \ + ../../guicast/bcpopupmenu.inc ../../guicast/bcpot.inc \ + ../../guicast/bcprogress.inc ../../guicast/bcrelocatablewidget.h \ + ../../guicast/bcrepeater.inc ../../guicast/bcresources.inc \ + ../../guicast/bcscrollbar.inc ../../guicast/bcslider.inc \ + ../../guicast/bcsubwindow.inc ../../guicast/bcsynchronous.inc \ + ../../guicast/bctextbox.inc ../../guicast/bctimer.inc \ + ../../guicast/bctitle.inc ../../guicast/bctoggle.inc \ + ../../guicast/bctumble.inc ../../guicast/bcwidgetgrid.inc \ + ../../guicast/bcwindow.inc ../../guicast/bcwindowbase.inc \ + ../../guicast/bcwindowevents.inc ../../guicast/condition.inc \ + ../../guicast/bchash.inc ../../guicast/linklist.h \ + ../../guicast/mutex.inc ../../guicast/vframe.inc \ + /usr/include/X11/Xatom.h /usr/include/X11/Xft/Xft.h \ + /usr/include/freetype2/ft2build.h \ + /usr/include/freetype2/config/ftheader.h \ + /usr/include/freetype2/freetype.h \ + /usr/include/freetype2/config/ftconfig.h \ + /usr/include/freetype2/config/ftconfig-64.h \ + /usr/include/freetype2/config/ftoption.h \ + /usr/include/freetype2/config/ftstdlib.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/limits.h \ + /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/syslimits.h \ + /usr/include/limits.h /usr/include/bits/posix1_lim.h \ + /usr/include/bits/local_lim.h /usr/include/linux/limits.h \ + /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \ + /usr/include/setjmp.h /usr/include/freetype2/fttypes.h \ + /usr/include/freetype2/ftsystem.h /usr/include/freetype2/ftimage.h \ + /usr/include/freetype2/fterrors.h /usr/include/freetype2/ftmoderr.h \ + /usr/include/freetype2/fterrdef.h /usr/include/fontconfig/fontconfig.h \ + /usr/include/sys/stat.h /usr/include/bits/stat.h \ + /usr/include/X11/extensions/Xrender.h /usr/include/X11/Xutil.h \ + /usr/include/X11/keysym.h /usr/include/X11/keysymdef.h \ + /usr/include/X11/extensions/render.h /usr/include/X11/Xdefs.h \ + /usr/include/X11/Xft/XftCompat.h /usr/include/X11/cursorfont.h \ + /usr/include/X11/extensions/xf86vmode.h /usr/include/X11/Xmd.h \ + /usr/include/X11/extensions/xf86vm.h /usr/include/GL/glx.h \ + /usr/include/GL/gl.h /usr/include/GL/glext.h /usr/include/inttypes.h \ + /usr/include/GL/glxext.h ../../guicast/bcbitmap.h /usr/include/sys/ipc.h \ + /usr/include/bits/ipctypes.h /usr/include/bits/ipc.h \ + /usr/include/sys/shm.h /usr/include/bits/shm.h \ + /usr/include/X11/extensions/XShm.h /usr/include/X11/extensions/shm.h \ + /usr/include/X11/extensions/Xvlib.h /usr/include/X11/extensions/Xv.h \ + ../../guicast/colors.h ../../guicast/sizes.h ../../guicast/bcbutton.h \ + ../../guicast/bcclipboard.h ../../guicast/thread.h \ + ../../guicast/bcdragwindow.h ../../guicast/bcpopup.h \ + ../../guicast/bclistboxitem.h ../../guicast/vframe.h \ + ../../guicast/bctexture.inc ../../quicktime/colormodels.h \ + ../../guicast/bccmodels.h ../../guicast/bcpan.h \ + ../../guicast/rotateframe.inc ../../guicast/bcfilebox.h \ + ../../guicast/bcdelete.inc ../../guicast/bclistboxitem.inc \ + ../../guicast/bcnewfolder.inc ../../guicast/bctextbox.h \ + ../../guicast/bclistbox.h ../../guicast/bcscrollbar.h \ + ../../guicast/bctoggle.h ../../guicast/fonts.h ../../guicast/bctumble.h \ + ../../guicast/bcwindow.h ../../guicast/filesystem.inc \ + ../../guicast/bcmenu.h ../../guicast/bcmenuitem.inc \ + ../../guicast/bcmenupopup.inc ../../guicast/bcmenubar.h \ + ../../guicast/bcmenu.inc ../../guicast/bcmenuitem.h \ + ../../guicast/bcmenupopup.h ../../guicast/bcmeter.h \ + ../../guicast/units.h ../../guicast/bcpopupmenu.h ../../guicast/bcpot.h \ + ../../guicast/bcpixmap.h ../../guicast/bcprogress.h \ + ../../guicast/bcrecentlist.h ../../guicast/bcresources.h \ + ../../guicast/bcdisplayinfo.inc ../../guicast/bcfontentry.inc \ + ../../guicast/bcsignals.inc ../../guicast/hashcache.inc \ + ../../guicast/bcslider.h ../../guicast/bcsynchronous.h \ + ../../guicast/bctexture.h ../../guicast/bctheme.h \ + ../../guicast/bctitle.h ../../guicast/bctimer.h /usr/include/sys/time.h \ + ../../guicast/error.h ../../guicast/debug.h ../../cinelerra/filexml.inc \ + ../../cinelerra/autos.inc ../../cinelerra/keyframes.inc \ + ../../cinelerra/messages.inc ../../cinelerra/mainprogress.inc \ + ../../cinelerra/plugincommands.h ../../cinelerra/pluginserver.inc \ + ../../cinelerra/theme.inc ../../guicast/vframe.h \ + ../../guicast/vframe.inc ../../guicast/rotateframe.inc motionwindow.h \ + motion.inc ../../cinelerra/pluginwindow.h ../../guicast/bcwindow.h + +/usr/include/stdc-predef.h: + +../../guicast/bcdisplayinfo.h: + +/usr/include/stdio.h: + +/usr/include/features.h: + +/usr/include/sys/cdefs.h: + +/usr/include/bits/wordsize.h: + +/usr/include/gnu/stubs.h: + +/usr/include/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h: + +/usr/include/bits/types.h: + +/usr/include/bits/typesizes.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdarg.h: + +/usr/include/bits/stdio_lim.h: + +/usr/include/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/bits/waitflags.h: + +/usr/include/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/bits/endian.h: + +/usr/include/bits/byteswap.h: + +/usr/include/bits/byteswap-16.h: + +/usr/include/xlocale.h: + +/usr/include/sys/types.h: + +/usr/include/time.h: + +/usr/include/sys/select.h: + +/usr/include/bits/select.h: + +/usr/include/bits/sigset.h: + +/usr/include/bits/time.h: + +/usr/include/sys/sysmacros.h: + +/usr/include/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/bits/stdlib-float.h: + +/usr/include/X11/Xlib.h: + +/usr/include/X11/X.h: + +/usr/include/X11/Xfuncproto.h: + +/usr/include/X11/Xosdefs.h: + +../../guicast/clip.h: + +../../guicast/language.h: + +/usr/include/libintl.h: + +motion.h: + +/usr/include/math.h: + +/usr/include/bits/math-vector.h: + +/usr/include/bits/libm-simd-decl-stubs.h: + +/usr/include/bits/huge_val.h: + +/usr/include/bits/huge_valf.h: + +/usr/include/bits/huge_vall.h: + +/usr/include/bits/inf.h: + +/usr/include/bits/nan.h: + +/usr/include/bits/mathdef.h: + +/usr/include/bits/mathcalls.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdint.h: + +/usr/include/stdint.h: + +/usr/include/bits/wchar.h: + +/usr/include/string.h: + +../../cinelerra/affine.inc: + +../../guicast/bchash.inc: + +../../cinelerra/filexml.inc: + +../../cinelerra/keyframe.inc: + +../../cinelerra/loadbalance.h: + +../../guicast/condition.inc: + +../../guicast/mutex.inc: + +../../guicast/thread.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/bits/sched.h: + +/usr/include/bits/timex.h: + +/usr/include/bits/setjmp.h: + +motionwindow.inc: + +../../cinelerra/overlayframe.inc: + +../../cinelerra/pluginvclient.h: + +../../cinelerra/maxbuffers.h: + +../../cinelerra/pluginclient.h: + +../../guicast/arraylist.h: + +../../guicast/condition.h: + +../../cinelerra/edlsession.inc: + +../../cinelerra/keyframe.h: + +../../cinelerra/auto.h: + +../../cinelerra/auto.inc: + +../../cinelerra/edl.inc: + +../../guicast/guicast.h: + +../../guicast/bcbar.h: + +../../guicast/bcsubwindow.h: + +../../guicast/arraylist.h: + +../../guicast/bcwindowbase.h: + +../../config.h: + +../../guicast/bcbar.inc: + +../../guicast/bcbitmap.inc: + +../../guicast/bcbutton.inc: + +../../guicast/bccapture.inc: + +../../guicast/bcclipboard.inc: + +../../guicast/bccmodels.inc: + +../../guicast/bcdragwindow.inc: + +../../guicast/bcfilebox.inc: + +../../guicast/bclistbox.inc: + +../../guicast/bcmenubar.inc: + +../../guicast/bcmeter.inc: + +../../guicast/bcpan.inc: + +../../guicast/bcpbuffer.inc: + +../../guicast/bcpixmap.inc: + +../../guicast/bcpopup.inc: + +../../guicast/bcpopupmenu.inc: + +../../guicast/bcpot.inc: + +../../guicast/bcprogress.inc: + +../../guicast/bcrelocatablewidget.h: + +../../guicast/bcrepeater.inc: + +../../guicast/bcresources.inc: + +../../guicast/bcscrollbar.inc: + +../../guicast/bcslider.inc: + +../../guicast/bcsubwindow.inc: + +../../guicast/bcsynchronous.inc: + +../../guicast/bctextbox.inc: + +../../guicast/bctimer.inc: + +../../guicast/bctitle.inc: + +../../guicast/bctoggle.inc: + +../../guicast/bctumble.inc: + +../../guicast/bcwidgetgrid.inc: + +../../guicast/bcwindow.inc: + +../../guicast/bcwindowbase.inc: + +../../guicast/bcwindowevents.inc: + +../../guicast/condition.inc: + +../../guicast/bchash.inc: + +../../guicast/linklist.h: + +../../guicast/mutex.inc: + +../../guicast/vframe.inc: + +/usr/include/X11/Xatom.h: + +/usr/include/X11/Xft/Xft.h: + +/usr/include/freetype2/ft2build.h: + +/usr/include/freetype2/config/ftheader.h: + +/usr/include/freetype2/freetype.h: + +/usr/include/freetype2/config/ftconfig.h: + +/usr/include/freetype2/config/ftconfig-64.h: + +/usr/include/freetype2/config/ftoption.h: + +/usr/include/freetype2/config/ftstdlib.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/limits.h: + +/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/syslimits.h: + +/usr/include/limits.h: + +/usr/include/bits/posix1_lim.h: + +/usr/include/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/bits/posix2_lim.h: + +/usr/include/bits/xopen_lim.h: + +/usr/include/setjmp.h: + +/usr/include/freetype2/fttypes.h: + +/usr/include/freetype2/ftsystem.h: + +/usr/include/freetype2/ftimage.h: + +/usr/include/freetype2/fterrors.h: + +/usr/include/freetype2/ftmoderr.h: + +/usr/include/freetype2/fterrdef.h: + +/usr/include/fontconfig/fontconfig.h: + +/usr/include/sys/stat.h: + +/usr/include/bits/stat.h: + +/usr/include/X11/extensions/Xrender.h: + +/usr/include/X11/Xutil.h: + +/usr/include/X11/keysym.h: + +/usr/include/X11/keysymdef.h: + +/usr/include/X11/extensions/render.h: + +/usr/include/X11/Xdefs.h: + +/usr/include/X11/Xft/XftCompat.h: + +/usr/include/X11/cursorfont.h: + +/usr/include/X11/extensions/xf86vmode.h: + +/usr/include/X11/Xmd.h: + +/usr/include/X11/extensions/xf86vm.h: + +/usr/include/GL/glx.h: + +/usr/include/GL/gl.h: + +/usr/include/GL/glext.h: + +/usr/include/inttypes.h: + +/usr/include/GL/glxext.h: + +../../guicast/bcbitmap.h: + +/usr/include/sys/ipc.h: + +/usr/include/bits/ipctypes.h: + +/usr/include/bits/ipc.h: + +/usr/include/sys/shm.h: + +/usr/include/bits/shm.h: + +/usr/include/X11/extensions/XShm.h: + +/usr/include/X11/extensions/shm.h: + +/usr/include/X11/extensions/Xvlib.h: + +/usr/include/X11/extensions/Xv.h: + +../../guicast/colors.h: + +../../guicast/sizes.h: + +../../guicast/bcbutton.h: + +../../guicast/bcclipboard.h: + +../../guicast/thread.h: + +../../guicast/bcdragwindow.h: + +../../guicast/bcpopup.h: + +../../guicast/bclistboxitem.h: + +../../guicast/vframe.h: + +../../guicast/bctexture.inc: + +../../quicktime/colormodels.h: + +../../guicast/bccmodels.h: + +../../guicast/bcpan.h: + +../../guicast/rotateframe.inc: + +../../guicast/bcfilebox.h: + +../../guicast/bcdelete.inc: + +../../guicast/bclistboxitem.inc: + +../../guicast/bcnewfolder.inc: + +../../guicast/bctextbox.h: + +../../guicast/bclistbox.h: + +../../guicast/bcscrollbar.h: + +../../guicast/bctoggle.h: + +../../guicast/fonts.h: + +../../guicast/bctumble.h: + +../../guicast/bcwindow.h: + +../../guicast/filesystem.inc: + +../../guicast/bcmenu.h: + +../../guicast/bcmenuitem.inc: + +../../guicast/bcmenupopup.inc: + +../../guicast/bcmenubar.h: + +../../guicast/bcmenu.inc: + +../../guicast/bcmenuitem.h: + +../../guicast/bcmenupopup.h: + +../../guicast/bcmeter.h: + +../../guicast/units.h: + +../../guicast/bcpopupmenu.h: + +../../guicast/bcpot.h: + +../../guicast/bcpixmap.h: + +../../guicast/bcprogress.h: + +../../guicast/bcrecentlist.h: + +../../guicast/bcresources.h: + +../../guicast/bcdisplayinfo.inc: + +../../guicast/bcfontentry.inc: + +../../guicast/bcsignals.inc: + +../../guicast/hashcache.inc: + +../../guicast/bcslider.h: + +../../guicast/bcsynchronous.h: + +../../guicast/bctexture.h: + +../../guicast/bctheme.h: + +../../guicast/bctitle.h: + +../../guicast/bctimer.h: + +/usr/include/sys/time.h: + +../../guicast/error.h: + +../../guicast/debug.h: + +../../cinelerra/filexml.inc: + +../../cinelerra/autos.inc: + +../../cinelerra/keyframes.inc: + +../../cinelerra/messages.inc: + +../../cinelerra/mainprogress.inc: + +../../cinelerra/plugincommands.h: + +../../cinelerra/pluginserver.inc: + +../../cinelerra/theme.inc: + +../../guicast/vframe.h: + +../../guicast/vframe.inc: + +../../guicast/rotateframe.inc: + +motionwindow.h: + +motion.inc: + +../../cinelerra/pluginwindow.h: + +../../guicast/bcwindow.h: diff --git a/cinelerra-5.1/plugins/motion-cv/.libs/motion.la b/cinelerra-5.1/plugins/motion-cv/.libs/motion.la new file mode 120000 index 00000000..3b77efb6 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/.libs/motion.la @@ -0,0 +1 @@ +../motion.la \ No newline at end of file diff --git a/cinelerra-5.1/plugins/motion-cv/.libs/motion.lai b/cinelerra-5.1/plugins/motion-cv/.libs/motion.lai new file mode 100644 index 00000000..c21dbc47 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/.libs/motion.lai @@ -0,0 +1,41 @@ +# motion.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='motion.so' + +# Names of this library. +library_names='motion.so motion.so motion.so' + +# The name of the static archive. +old_library='' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/a52dec-0.7.4/liba52/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/faac-1.28/common/mp4v2 -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/faac-1.28/libfaac/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/faad2-2.7/common/mp4ff -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/faad2-2.7/libfaad/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/lame-3.99.5/libmp3lame/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/lame-3.99.5/mpglib/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/libuuid-1.0.3/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/mjpegtools-2.1.0/lavtools/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/mjpegtools-2.1.0/mpeg2enc/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/mjpegtools-2.1.0/mplex/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/mjpegtools-2.1.0/utils/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/mjpegtools-2.1.0/utils/mmxsse/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/mjpegtools-2.1.0/yuvfilters/.libs -L/mnt0/build5/cinelerra-cv/thirdparty/../thirdparty/x264-snapshot-20160220-2245-stable -ldl -lpthread' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for motion. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=yes + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib/cinelerra' diff --git a/cinelerra-5.1/plugins/motion-cv/.libs/motion.so b/cinelerra-5.1/plugins/motion-cv/.libs/motion.so new file mode 100755 index 00000000..2829316e Binary files /dev/null and b/cinelerra-5.1/plugins/motion-cv/.libs/motion.so differ diff --git a/cinelerra-5.1/plugins/motion-cv/Makefile b/cinelerra-5.1/plugins/motion-cv/Makefile new file mode 100644 index 00000000..a0900168 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/Makefile @@ -0,0 +1,13 @@ +include ../../plugin_defs + +OBJS := \ + $(OBJDIR)/motion-cv.o \ + $(OBJDIR)/motionwindow-cv.o + +PLUGIN = motion-cv + +include ../../plugin_config + +$(OBJDIR)/motion-cv.o: motion-cv.C +$(OBJDIR)/motionwindow-cv.o: motionwindow-cv.C + diff --git a/cinelerra-5.1/plugins/motion-cv/motion-cv.C b/cinelerra-5.1/plugins/motion-cv/motion-cv.C new file mode 100644 index 00000000..9a702503 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/motion-cv.C @@ -0,0 +1,2655 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 "affine.h" +#include "bcdisplayinfo.h" +#include "clip.h" +#include "bchash.h" +#include "bcsignals.h" +#include "filexml.h" +#include "keyframe.h" +#include "language.h" +#include "motion-cv.h" +#include "motionwindow-cv.h" +#include "mutex.h" +#include "overlayframe.h" +#include "rotateframe.h" +#include "transportque.h" + + +#include +#include + +REGISTER_PLUGIN(MotionCVMain) + +//#undef DEBUG + +#ifndef DEBUG +#define DEBUG +#endif + + +MotionCVConfig::MotionCVConfig() +{ + global_range_w = 5; + global_range_h = 5; + rotation_range = 5; + block_count = 1; + global_block_w = MIN_BLOCK; + global_block_h = MIN_BLOCK; + rotation_block_w = MIN_BLOCK; + rotation_block_h = MIN_BLOCK; + block_x = 50; + block_y = 50; + global_positions = 256; + rotate_positions = 4; + magnitude = 100; + return_speed = 0; + mode1 = STABILIZE; + global = 1; + rotate = 1; + addtrackedframeoffset = 0; + strcpy(tracking_file, TRACKING_FILE); + mode2 = RECALCULATE; + draw_vectors = 1; + mode3 = MotionCVConfig::TRACK_SINGLE; + track_frame = 0; + bottom_is_master = 1; + horizontal_only = 0; + vertical_only = 0; +} + +void MotionCVConfig::boundaries() +{ + CLAMP(global_range_w, MIN_RADIUS, MAX_RADIUS); + CLAMP(global_range_h, MIN_RADIUS, MAX_RADIUS); + CLAMP(rotation_range, MIN_ROTATION, MAX_ROTATION); + CLAMP(block_count, MIN_BLOCKS, MAX_BLOCKS); + CLAMP(global_block_w, MIN_BLOCK, MAX_BLOCK); + CLAMP(global_block_h, MIN_BLOCK, MAX_BLOCK); + CLAMP(rotation_block_w, MIN_BLOCK, MAX_BLOCK); + CLAMP(rotation_block_h, MIN_BLOCK, MAX_BLOCK); +} + +int MotionCVConfig::equivalent(MotionCVConfig &that) +{ + return global_range_w == that.global_range_w && + global_range_h == that.global_range_h && + rotation_range == that.rotation_range && + mode1 == that.mode1 && + global == that.global && + rotate == that.rotate && + addtrackedframeoffset == that.addtrackedframeoffset && + !strcmp(tracking_file, that.tracking_file) && + draw_vectors == that.draw_vectors && + block_count == that.block_count && + global_block_w == that.global_block_w && + global_block_h == that.global_block_h && + rotation_block_w == that.rotation_block_w && + rotation_block_h == that.rotation_block_h && + EQUIV(block_x, that.block_x) && + EQUIV(block_y, that.block_y) && + global_positions == that.global_positions && + rotate_positions == that.rotate_positions && + magnitude == that.magnitude && + return_speed == that.return_speed && + mode3 == that.mode3 && + track_frame == that.track_frame && + bottom_is_master == that.bottom_is_master && + horizontal_only == that.horizontal_only && + vertical_only == that.vertical_only; +} + +void MotionCVConfig::copy_from(MotionCVConfig &that) +{ + global_range_w = that.global_range_w; + global_range_h = that.global_range_h; + rotation_range = that.rotation_range; + mode1 = that.mode1; + global = that.global; + rotate = that.rotate; + addtrackedframeoffset = that.addtrackedframeoffset; + strcpy(tracking_file, that.tracking_file); + mode2 = that.mode2; + draw_vectors = that.draw_vectors; + block_count = that.block_count; + block_x = that.block_x; + block_y = that.block_y; + global_positions = that.global_positions; + rotate_positions = that.rotate_positions; + global_block_w = that.global_block_w; + global_block_h = that.global_block_h; + rotation_block_w = that.rotation_block_w; + rotation_block_h = that.rotation_block_h; + magnitude = that.magnitude; + return_speed = that.return_speed; + mode3 = that.mode3; + track_frame = that.track_frame; + bottom_is_master = that.bottom_is_master; + horizontal_only = that.horizontal_only; + vertical_only = that.vertical_only; +} + +void MotionCVConfig::interpolate(MotionCVConfig &prev, MotionCVConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame) +{ + copy_from(prev); +} + +MotionCVMain::MotionCVMain(PluginServer *server) + : PluginVClient(server) +{ + engine = 0; + rotate_engine = 0; + motion_rotate = 0; + total_dx = 0; + total_dy = 0; + total_angle = 0; + overlayer = 0; + search_area = 0; + search_size = 0; + temp_frame = 0; + previous_frame_number = -1; + + prev_global_ref = 0; + current_global_ref = 0; + global_target_src = 0; + global_target_dst = 0; + + active_fp = 0; + active_file[0] = 0; + tracking_frame = -1; + dx_offset = dy_offset = 0; + save_dx = load_dx = 0; + save_dy = load_dy = 0; + save_dt = load_dt = 0; + + prev_rotate_ref = 0; + current_rotate_ref = 0; + rotate_target_src = 0; + rotate_target_dst = 0; +} + +MotionCVMain::~MotionCVMain() +{ + + delete engine; + delete overlayer; + delete [] search_area; + delete temp_frame; + delete rotate_engine; + delete motion_rotate; + + delete prev_global_ref; + delete current_global_ref; + delete global_target_src; + delete global_target_dst; + + if( active_fp ) fclose(active_fp); + + delete prev_rotate_ref; + delete current_rotate_ref; + delete rotate_target_src; + delete rotate_target_dst; +} + +const char* MotionCVMain::plugin_title() { return _("MotionCV"); } +int MotionCVMain::is_realtime() { return 1; } +int MotionCVMain::is_multichannel() { return 1; } + + +NEW_WINDOW_MACRO(MotionCVMain, MotionCVWindow) + +LOAD_CONFIGURATION_MACRO(MotionCVMain, MotionCVConfig) + + + +void MotionCVMain::update_gui() +{ + if(thread) + { + if(load_configuration()) + { + thread->window->lock_window("MotionCVMain::update_gui"); + MotionCVWindow *window = (MotionCVWindow *)thread->window; + + char string[BCTEXTLEN]; + sprintf(string, "%d", config.global_positions); + window->global_search_positions->set_text(string); + sprintf(string, "%d", config.rotate_positions); + window->rotation_search_positions->set_text(string); + + window->global_block_w->update(config.global_block_w); + window->global_block_h->update(config.global_block_h); + window->rotation_block_w->update(config.rotation_block_w); + window->rotation_block_h->update(config.rotation_block_h); + window->block_x->update(config.block_x); + window->block_y->update(config.block_y); + window->block_x_text->update((float)config.block_x); + window->block_y_text->update((float)config.block_y); + window->magnitude->update(config.magnitude); + window->return_speed->update(config.return_speed); + + + window->track_single->update(config.mode3 == MotionCVConfig::TRACK_SINGLE); + window->track_frame_number->update(config.track_frame); + window->track_previous->update(config.mode3 == MotionCVConfig::TRACK_PREVIOUS); + window->previous_same->update(config.mode3 == MotionCVConfig::PREVIOUS_SAME_BLOCK); + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + window->track_frame_number->disable(); + else + window->track_frame_number->enable(); + + window->mode1->set_text( + Mode1::to_text(config.mode1)); + window->mode2->set_text( + Mode2::to_text(config.mode2)); + window->mode3->set_text( + Mode3::to_text(config.horizontal_only, config.vertical_only)); + window->master_layer->set_text( + MasterLayer::to_text(config.bottom_is_master)); + + + window->update_mode(); + window->unlock_window(); + } + } +} + + + + +void MotionCVMain::save_data(KeyFrame *keyframe) +{ + FileXML output; + +// cause data to be stored directly in text + output.set_shared_output(keyframe->get_data(), MESSAGESIZE); + output.tag.set_title("MOTION"); + + output.tag.set_property("BLOCK_COUNT", config.block_count); + output.tag.set_property("GLOBAL_POSITIONS", config.global_positions); + output.tag.set_property("ROTATE_POSITIONS", config.rotate_positions); + output.tag.set_property("GLOBAL_BLOCK_W", config.global_block_w); + output.tag.set_property("GLOBAL_BLOCK_H", config.global_block_h); + output.tag.set_property("ROTATION_BLOCK_W", config.rotation_block_w); + output.tag.set_property("ROTATION_BLOCK_H", config.rotation_block_h); + output.tag.set_property("BLOCK_X", config.block_x); + output.tag.set_property("BLOCK_Y", config.block_y); + output.tag.set_property("GLOBAL_RANGE_W", config.global_range_w); + output.tag.set_property("GLOBAL_RANGE_H", config.global_range_h); + output.tag.set_property("ROTATION_RANGE", config.rotation_range); + output.tag.set_property("MAGNITUDE", config.magnitude); + output.tag.set_property("RETURN_SPEED", config.return_speed); + output.tag.set_property("MODE1", config.mode1); + output.tag.set_property("GLOBAL", config.global); + output.tag.set_property("ROTATE", config.rotate); + output.tag.set_property("ADDTRACKEDFRAMEOFFSET", config.addtrackedframeoffset); + output.tag.set_property("TRACKING_FILE", config.tracking_file); + output.tag.set_property("MODE2", config.mode2); + output.tag.set_property("DRAW_VECTORS", config.draw_vectors); + output.tag.set_property("MODE3", config.mode3); + output.tag.set_property("TRACK_FRAME", config.track_frame); + output.tag.set_property("BOTTOM_IS_MASTER", config.bottom_is_master); + output.tag.set_property("HORIZONTAL_ONLY", config.horizontal_only); + output.tag.set_property("VERTICAL_ONLY", config.vertical_only); + output.append_tag(); + output.tag.set_title("/MOTION"); + output.append_tag(); + output.terminate_string(); +} + +void MotionCVMain::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + + int result = 0; + + while(!result) + { + result = input.read_tag(); + + if(!result) + { + if(input.tag.title_is("MOTION")) + { + config.block_count = input.tag.get_property("BLOCK_COUNT", config.block_count); + config.global_positions = input.tag.get_property("GLOBAL_POSITIONS", config.global_positions); + config.rotate_positions = input.tag.get_property("ROTATE_POSITIONS", config.rotate_positions); + config.global_block_w = input.tag.get_property("GLOBAL_BLOCK_W", config.global_block_w); + config.global_block_h = input.tag.get_property("GLOBAL_BLOCK_H", config.global_block_h); + config.rotation_block_w = input.tag.get_property("ROTATION_BLOCK_W", config.rotation_block_w); + config.rotation_block_h = input.tag.get_property("ROTATION_BLOCK_H", config.rotation_block_h); + config.block_x = input.tag.get_property("BLOCK_X", config.block_x); + config.block_y = input.tag.get_property("BLOCK_Y", config.block_y); + config.global_range_w = input.tag.get_property("GLOBAL_RANGE_W", config.global_range_w); + config.global_range_h = input.tag.get_property("GLOBAL_RANGE_H", config.global_range_h); + config.rotation_range = input.tag.get_property("ROTATION_RANGE", config.rotation_range); + config.magnitude = input.tag.get_property("MAGNITUDE", config.magnitude); + config.return_speed = input.tag.get_property("RETURN_SPEED", config.return_speed); + config.mode1 = input.tag.get_property("MODE1", config.mode1); + config.global = input.tag.get_property("GLOBAL", config.global); + config.rotate = input.tag.get_property("ROTATE", config.rotate); + config.addtrackedframeoffset = input.tag.get_property("ADDTRACKEDFRAMEOFFSET", config.addtrackedframeoffset); + input.tag.get_property("TRACKING_FILE", config.tracking_file); + config.mode2 = input.tag.get_property("MODE2", config.mode2); + config.draw_vectors = input.tag.get_property("DRAW_VECTORS", config.draw_vectors); + config.mode3 = input.tag.get_property("MODE3", config.mode3); + config.track_frame = input.tag.get_property("TRACK_FRAME", config.track_frame); + config.bottom_is_master = input.tag.get_property("BOTTOM_IS_MASTER", config.bottom_is_master); + config.horizontal_only = input.tag.get_property("HORIZONTAL_ONLY", config.horizontal_only); + config.vertical_only = input.tag.get_property("VERTICAL_ONLY", config.vertical_only); + } + } + } + config.boundaries(); +} + + + + + + + + + +void MotionCVMain::allocate_temp(int w, int h, int color_model) +{ + if(temp_frame && + (temp_frame->get_w() != w || + temp_frame->get_h() != h)) + { + delete temp_frame; + temp_frame = 0; + } + if(!temp_frame) + temp_frame = new VFrame(w, h, color_model); +} + + + +void MotionCVMain::process_global() +{ + if(!engine) engine = new MotionCVScan(this, + PluginClient::get_project_smp() + 1, + PluginClient::get_project_smp() + 1); + +// Get the current motion vector between the previous and current frame + engine->scan_frame(current_global_ref, prev_global_ref); + current_dx = engine->dx_result; + current_dy = engine->dy_result; + +// Add current motion vector to accumulation vector. + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + { +// Retract over time + total_dx = (int64_t)total_dx * (100 - config.return_speed) / 100; + total_dy = (int64_t)total_dy * (100 - config.return_speed) / 100; + total_dx += engine->dx_result; + total_dy += engine->dy_result; + } + else +// Make accumulation vector current + { + total_dx = engine->dx_result; + total_dy = engine->dy_result; + } + +// Clamp accumulation vector + if(config.magnitude < 100) + { + //int block_w = (int64_t)config.global_block_w * + // current_global_ref->get_w() / 100; + //int block_h = (int64_t)config.global_block_h * + // current_global_ref->get_h() / 100; + int block_x_orig = (int64_t)(config.block_x * + current_global_ref->get_w() / + 100); + int block_y_orig = (int64_t)(config.block_y * + current_global_ref->get_h() / + 100); + + int max_block_x = (int64_t)(current_global_ref->get_w() - block_x_orig) * + OVERSAMPLE * + config.magnitude / + 100; + int max_block_y = (int64_t)(current_global_ref->get_h() - block_y_orig) * + OVERSAMPLE * + config.magnitude / + 100; + int min_block_x = (int64_t)-block_x_orig * + OVERSAMPLE * + config.magnitude / + 100; + int min_block_y = (int64_t)-block_y_orig * + OVERSAMPLE * + config.magnitude / + 100; + + CLAMP(total_dx, min_block_x, max_block_x); + CLAMP(total_dy, min_block_y, max_block_y); + } + +#ifdef DEBUG +printf("MotionCVMain::process_global 2 total_dx=%.02f total_dy=%.02f\n", +(float)total_dx / OVERSAMPLE, +(float)total_dy / OVERSAMPLE); +#endif + + if(config.mode3 != MotionCVConfig::TRACK_SINGLE && !config.rotate) + { +// Transfer current reference frame to previous reference frame and update +// counter. Must wait for rotate to compare. + prev_global_ref->copy_from(current_global_ref); + previous_frame_number = get_source_position(); + } + +// Decide what to do with target based on requested operation + int interpolation = NEAREST_NEIGHBOR; + float dx = 0; + float dy = 0; + switch(config.mode1) + { + case MotionCVConfig::NOTHING: + global_target_dst->copy_from(global_target_src); + break; + case MotionCVConfig::TRACK_PIXEL: + interpolation = NEAREST_NEIGHBOR; + dx = (int)(total_dx / OVERSAMPLE); + dy = (int)(total_dy / OVERSAMPLE); + break; + case MotionCVConfig::STABILIZE_PIXEL: + interpolation = NEAREST_NEIGHBOR; + dx = -(int)(total_dx / OVERSAMPLE); + dy = -(int)(total_dy / OVERSAMPLE); + break; + break; + case MotionCVConfig::TRACK: + interpolation = CUBIC_LINEAR; + dx = (float)total_dx / OVERSAMPLE; + dy = (float)total_dy / OVERSAMPLE; + break; + case MotionCVConfig::STABILIZE: + interpolation = CUBIC_LINEAR; + dx = -(float)total_dx / OVERSAMPLE; + dy = -(float)total_dy / OVERSAMPLE; + break; + } + + + if(config.mode1 != MotionCVConfig::NOTHING) + { + if(!overlayer) + overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); + global_target_dst->clear_frame(); + overlayer->overlay(global_target_dst, + global_target_src, + 0, + 0, + global_target_src->get_w(), + global_target_src->get_h(), + dx, + dy, + (float)global_target_src->get_w() + dx, + (float)global_target_src->get_h() + dy, + 1, + TRANSFER_REPLACE, + interpolation); + } +} + + + +void MotionCVMain::process_rotation() +{ + int block_x; + int block_y; + +// Convert the previous global reference into the previous rotation reference. +// Convert global target destination into rotation target source. + if(config.global) + { + if(!overlayer) + overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); + float dx; + float dy; + if(config.mode3 == MotionCVConfig::TRACK_SINGLE) + { + dx = (float)total_dx / OVERSAMPLE; + dy = (float)total_dy / OVERSAMPLE; + } + else + { + dx = (float)current_dx / OVERSAMPLE; + dy = (float)current_dy / OVERSAMPLE; + } + + prev_rotate_ref->clear_frame(); + overlayer->overlay(prev_rotate_ref, + prev_global_ref, + 0, + 0, + prev_global_ref->get_w(), + prev_global_ref->get_h(), + dx, + dy, + (float)prev_global_ref->get_w() + dx, + (float)prev_global_ref->get_h() + dy, + 1, + TRANSFER_REPLACE, + CUBIC_LINEAR); +// Pivot is destination global position + block_x = (int)(prev_rotate_ref->get_w() * + config.block_x / + 100 + + (float)total_dx / + OVERSAMPLE); + block_y = (int)(prev_rotate_ref->get_h() * + config.block_y / + 100 + + (float)total_dy / + OVERSAMPLE); +// Use the global target output as the rotation target input + rotate_target_src->copy_from(global_target_dst); +// Transfer current reference frame to previous reference frame for global. + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + { + prev_global_ref->copy_from(current_global_ref); + previous_frame_number = get_source_position(); + } + } + else + { +// Pivot is fixed + block_x = (int)(prev_rotate_ref->get_w() * + config.block_x / + 100); + block_y = (int)(prev_rotate_ref->get_h() * + config.block_y / + 100); + } + + + +// Get rotation + if(!motion_rotate) + motion_rotate = new RotateCVScan(this, + get_project_smp() + 1, + get_project_smp() + 1); + + current_angle = motion_rotate->scan_frame(prev_rotate_ref, + current_rotate_ref, + block_x, + block_y); + + + +// Add current rotation to accumulation + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + { +// Retract over time + total_angle = total_angle * (100 - config.return_speed) / 100; + total_angle += current_angle; + + if(!config.global) + { +// Transfer current reference frame to previous reference frame and update +// counter. + prev_rotate_ref->copy_from(current_rotate_ref); + previous_frame_number = get_source_position(); + } + } + else + { + total_angle = current_angle; + } + +#ifdef DEBUG +printf("MotionCVMain::process_rotation total_angle=%f\n", total_angle); +#endif + + +// Calculate rotation parameters based on requested operation + float angle = 0; + switch(config.mode1) + { + case MotionCVConfig::NOTHING: + rotate_target_dst->copy_from(rotate_target_src); + break; + case MotionCVConfig::TRACK: + case MotionCVConfig::TRACK_PIXEL: + angle = total_angle; + break; + case MotionCVConfig::STABILIZE: + case MotionCVConfig::STABILIZE_PIXEL: + angle = -total_angle; + break; + } + + + + if(config.mode1 != MotionCVConfig::NOTHING) + { + if(!rotate_engine) + rotate_engine = new AffineEngine(PluginClient::get_project_smp() + 1, + PluginClient::get_project_smp() + 1); + + rotate_target_dst->clear_frame(); + +// Determine pivot based on a number of factors. + switch(config.mode1) + { + case MotionCVConfig::TRACK: + case MotionCVConfig::TRACK_PIXEL: +// Use destination of global tracking. + rotate_engine->set_pivot(block_x, block_y); + break; + + case MotionCVConfig::STABILIZE: + case MotionCVConfig::STABILIZE_PIXEL: + if(config.global) + { +// Use origin of global stabilize operation + rotate_engine->set_pivot((int)(rotate_target_dst->get_w() * + config.block_x / + 100), + (int)(rotate_target_dst->get_h() * + config.block_y / + 100)); + + } + else + { +// Use origin + rotate_engine->set_pivot(block_x, block_y); + } + break; + } + + + rotate_engine->rotate(rotate_target_dst, rotate_target_src, angle); +// overlayer->overlay(rotate_target_dst, +// prev_rotate_ref, +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 1, +// TRANSFER_NORMAL, +// CUBIC_LINEAR); +// overlayer->overlay(rotate_target_dst, +// current_rotate_ref, +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 1, +// TRANSFER_NORMAL, +// CUBIC_LINEAR); + + + } + + +} + + + + + + + + + +int MotionCVMain::process_buffer(VFrame **frame, + int64_t start_position, + double frame_rate) +{ + int prev_config_mode2 = config.mode2; + int need_reconfigure = load_configuration(); + int color_model = frame[0]->get_color_model(); + w = frame[0]->get_w(); + h = frame[0]->get_h(); + + +#ifdef DEBUG +printf("MotionCVMain::process_buffer 1 start_position=%jd\n", start_position); +#endif + + +// Calculate the source and destination pointers for each of the operations. +// Get the layer to track motion in. + reference_layer = config.bottom_is_master ? + PluginClient::total_in_buffers - 1 : + 0; +// Get the layer to apply motion in. + target_layer = config.bottom_is_master ? + 0 : + PluginClient::total_in_buffers - 1; + + + output_frame = frame[target_layer]; + + +// Get the position of previous reference frame. + int64_t actual_previous_number; +// Skip if match frame not available + int skip_current = 0; + + + if(config.mode3 == MotionCVConfig::TRACK_SINGLE) + { + actual_previous_number = config.track_frame; + if(get_direction() == PLAY_REVERSE) + actual_previous_number++; + if(actual_previous_number == start_position) + skip_current = 1; + } + else + { + actual_previous_number = start_position; + if(get_direction() == PLAY_FORWARD) + { + actual_previous_number--; + if(actual_previous_number < get_source_start()) + skip_current = 1; + else + { + KeyFrame *keyframe = get_prev_keyframe(start_position, 1); + if(keyframe->position > 0 && + actual_previous_number < keyframe->position) + skip_current = 1; + } + } + else + { + actual_previous_number++; + if(actual_previous_number >= get_source_start() + get_total_len()) + skip_current = 1; + else + { + KeyFrame *keyframe = get_next_keyframe(start_position, 1); + if(keyframe->position > 0 && + actual_previous_number >= keyframe->position) + skip_current = 1; + } + } + +// Only count motion since last keyframe + + + } + + + if(!config.global && !config.rotate) skip_current = 1; + + + + +// printf("process_realtime %d %lld %lld\n", +// skip_current, +// previous_frame_number, +// actual_previous_number); +// Load match frame and reset vectors + int need_reload = !skip_current && + (previous_frame_number != actual_previous_number || + need_reconfigure); + if(need_reload) + { + total_dx = 0; + total_dy = 0; + total_angle = 0; + previous_frame_number = actual_previous_number; + } + if( prev_config_mode2 != MotionCVConfig::SAVE && + config.mode2 == MotionCVConfig::SAVE ) { +#ifdef DEBUG +printf("MotionCVMain::process_buffer 2 remove tracking file: %s\n", config.tracking_file); +#endif + ::remove(config.tracking_file); + } + + + if(skip_current) + { + total_dx = 0; + total_dy = 0; + current_dx = 0; + current_dy = 0; + total_angle = 0; + current_angle = 0; + } + + + + +// Get the global pointers. Here we walk through the sequence of events. + if(config.global) + { +// Assume global only. Global reads previous frame and compares +// with current frame to get the current translation. +// The center of the search area is fixed in compensate mode or +// the user value + the accumulation vector in track mode. + if(!prev_global_ref) + prev_global_ref = new VFrame(w, h, color_model); + if(!current_global_ref) + current_global_ref = new VFrame(w, h, color_model); + +// Global loads the current target frame into the src and +// writes it to the dst frame with desired translation. + if(!global_target_src) + global_target_src = new VFrame(w, h, color_model); + if(!global_target_dst) + global_target_dst = new VFrame(w, h, color_model); + + +// Load the global frames + if(need_reload) + { + read_frame(prev_global_ref, + reference_layer, + previous_frame_number, + frame_rate, + 0); + } + + read_frame(current_global_ref, + reference_layer, + start_position, + frame_rate, + 0); + read_frame(global_target_src, + target_layer, + start_position, + frame_rate, + 0); + + + +// Global followed by rotate + if(config.rotate) + { +// Must translate the previous global reference by the current global +// accumulation vector to match the current global reference. +// The center of the search area is always the user value + the accumulation +// vector. + if(!prev_rotate_ref) + prev_rotate_ref = new VFrame(w, h, color_model); +// The current global reference is the current rotation reference. + if(!current_rotate_ref) + current_rotate_ref = new VFrame(w, h, color_model); + current_rotate_ref->copy_from(current_global_ref); + +// The global target destination is copied to the rotation target source +// then written to the rotation output with rotation. +// The pivot for the rotation is the center of the search area +// if we're tracking. +// The pivot is fixed to the user position if we're compensating. + if(!rotate_target_src) + rotate_target_src = new VFrame(w, h, color_model); + if(!rotate_target_dst) + rotate_target_dst = new VFrame(w,h , color_model); + } + } + else +// Rotation only + if(config.rotate) + { +// Rotation reads the previous reference frame and compares it with current +// reference frame. + if(!prev_rotate_ref) + prev_rotate_ref = new VFrame(w, h, color_model); + if(!current_rotate_ref) + current_rotate_ref = new VFrame(w, h, color_model); + +// Rotation loads target frame to temporary, rotates it, and writes it to the +// target frame. The pivot is always fixed. + if(!rotate_target_src) + rotate_target_src = new VFrame(w, h, color_model); + if(!rotate_target_dst) + rotate_target_dst = new VFrame(w,h , color_model); + + +// Load the rotate frames + if(need_reload) + { + read_frame(prev_rotate_ref, + reference_layer, + previous_frame_number, + frame_rate, + 0); + } + read_frame(current_rotate_ref, + reference_layer, + start_position, + frame_rate, + 0); + read_frame(rotate_target_src, + target_layer, + start_position, + frame_rate, + 0); + } + + if(!skip_current) + { + + if( config.mode2 == MotionCVConfig::LOAD ) { + char line[BCTEXTLEN]; + int64_t frame_no, no; int dx, dy; float dt; + if( config.addtrackedframeoffset && config.track_frame != tracking_frame ) { + tracking_frame = frame_no = config.track_frame; + if( !get_line_key(config.tracking_file, frame_no, line, sizeof(line)) && + sscanf(line, "%jd %d %d %f", &no, &dx, &dy, &dt) == 4 ) { + dx_offset = dx; dy_offset = dy; + } + else { +#ifdef DEBUG + printf("MotionCVMain::process_buffer: no offset data frame %jd\n", frame_no); +#endif + } + } +// Load result from disk + frame_no = get_source_position(); + if( !get_line_key(config.tracking_file, frame_no, line, sizeof(line)) && + sscanf(line, "%jd %d %d %f", &frame_no, &dx, &dy, &dt) == 4 ) { + load_dx = dx; load_dy = dy; load_dt = dt; + } + else { +#ifdef DEBUG + printf("MotionCVMain::process_buffer: no tracking data frame %jd\n", frame_no); +#endif + } + } + +// Get position change from previous frame to current frame + if(config.global) process_global(); +// Get rotation change from previous frame to current frame + if(config.rotate) process_rotation(); +//frame[target_layer]->copy_from(prev_rotate_ref); +//frame[target_layer]->copy_from(current_rotate_ref); + +// write results to disk + if( config.mode2 == MotionCVConfig::SAVE ) { + FILE *output = fopen(config.tracking_file, "aw"); + if( output ) { + int64_t frame_no = get_source_position(); + fprintf(output, "%jd %d %d %f\n", frame_no, save_dx, save_dy, save_dt); + fclose(output); + } + else { + perror("MotionCVMain::process buffer save"); + } + } + } + + +// Transfer the relevant target frame to the output + if(!skip_current) + { + if(config.rotate) + { + frame[target_layer]->copy_from(rotate_target_dst); + } + else + { + frame[target_layer]->copy_from(global_target_dst); + } + } + else +// Read the target destination directly + { + read_frame(frame[target_layer], + target_layer, + start_position, + frame_rate, + 0); + } + + if(config.draw_vectors) + { + draw_vectors(frame[target_layer]); + } + +#ifdef DEBUG +printf("MotionCVMain::process_buffer 100\n"); +#endif + return 0; +} + + +void MotionCVMain::clamp_scan(int w, + int h, + int *block_x1, + int *block_y1, + int *block_x2, + int *block_y2, + int *scan_x1, + int *scan_y1, + int *scan_x2, + int *scan_y2, + int use_absolute) +{ +// printf("MotionCVMain::clamp_scan 1 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", +// w, +// h, +// *block_x1, +// *block_y1, +// *block_x2, +// *block_y2, +// *scan_x1, +// *scan_y1, +// *scan_x2, +// *scan_y2, +// use_absolute); + + if(use_absolute) + { +// scan is always out of range before block. + if(*scan_x1 < 0) + { + int difference = -*scan_x1; + *block_x1 += difference; + *scan_x1 = 0; + } + + if(*scan_y1 < 0) + { + int difference = -*scan_y1; + *block_y1 += difference; + *scan_y1 = 0; + } + + if(*scan_x2 > w) + { + int difference = *scan_x2 - w; + *block_x2 -= difference; + *scan_x2 -= difference; + } + + if(*scan_y2 > h) + { + int difference = *scan_y2 - h; + *block_y2 -= difference; + *scan_y2 -= difference; + } + + CLAMP(*scan_x1, 0, w); + CLAMP(*scan_y1, 0, h); + CLAMP(*scan_x2, 0, w); + CLAMP(*scan_y2, 0, h); + } + else + { + if(*scan_x1 < 0) + { + int difference = -*scan_x1; + *block_x1 += difference; + *scan_x2 += difference; + *scan_x1 = 0; + } + + if(*scan_y1 < 0) + { + int difference = -*scan_y1; + *block_y1 += difference; + *scan_y2 += difference; + *scan_y1 = 0; + } + + if(*scan_x2 - *block_x1 + *block_x2 > w) + { + int difference = *scan_x2 - *block_x1 + *block_x2 - w; + *block_x2 -= difference; + } + + if(*scan_y2 - *block_y1 + *block_y2 > h) + { + int difference = *scan_y2 - *block_y1 + *block_y2 - h; + *block_y2 -= difference; + } + +// CLAMP(*scan_x1, 0, w - (*block_x2 - *block_x1)); +// CLAMP(*scan_y1, 0, h - (*block_y2 - *block_y1)); +// CLAMP(*scan_x2, 0, w - (*block_x2 - *block_x1)); +// CLAMP(*scan_y2, 0, h - (*block_y2 - *block_y1)); + } + +// Sanity checks which break the calculation but should never happen if the +// center of the block is inside the frame. + CLAMP(*block_x1, 0, w); + CLAMP(*block_x2, 0, w); + CLAMP(*block_y1, 0, h); + CLAMP(*block_y2, 0, h); + +// printf("MotionCVMain::clamp_scan 2 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", +// w, +// h, +// *block_x1, +// *block_y1, +// *block_x2, +// *block_y2, +// *scan_x1, +// *scan_y1, +// *scan_x2, +// *scan_y2, +// use_absolute); +} + + + +void MotionCVMain::draw_vectors(VFrame *frame) +{ + int w = frame->get_w(); + int h = frame->get_h(); + int global_x1, global_y1; + int global_x2, global_y2; + int block_x, block_y; + int block_w, block_h; + int block_x1, block_y1; + int block_x2, block_y2; + int block_x3, block_y3; + int block_x4, block_y4; + int search_w, search_h; + int search_x1, search_y1; + int search_x2, search_y2; + //int search_x3, search_y3; + //int search_x4, search_y4; + + if(config.global) + { +// Get vector +// Start of vector is center of previous block. +// End of vector is total accumulation. + if(config.mode3 == MotionCVConfig::TRACK_SINGLE) + { + global_x1 = (int64_t)(config.block_x * + w / + 100); + global_y1 = (int64_t)(config.block_y * + h / + 100); + global_x2 = global_x1 + total_dx / OVERSAMPLE; + global_y2 = global_y1 + total_dy / OVERSAMPLE; +//printf("MotionCVMain::draw_vectors %d %d %d %d %d %d\n", total_dx, total_dy, global_x1, global_y1, global_x2, global_y2); + } + else +// Start of vector is center of previous block. +// End of vector is current change. + if(config.mode3 == MotionCVConfig::PREVIOUS_SAME_BLOCK) + { + global_x1 = (int64_t)(config.block_x * + w / + 100); + global_y1 = (int64_t)(config.block_y * + h / + 100); + global_x2 = global_x1 + current_dx / OVERSAMPLE; + global_y2 = global_y1 + current_dy / OVERSAMPLE; + } + else + { + global_x1 = (int64_t)(config.block_x * + w / + 100 + + (total_dx - current_dx) / + OVERSAMPLE); + global_y1 = (int64_t)(config.block_y * + h / + 100 + + (total_dy - current_dy) / + OVERSAMPLE); + global_x2 = (int64_t)(config.block_x * + w / + 100 + + total_dx / + OVERSAMPLE); + global_y2 = (int64_t)(config.block_y * + h / + 100 + + total_dy / + OVERSAMPLE); + } + + block_x = global_x1; + block_y = global_y1; + block_w = config.global_block_w * w / 100; + block_h = config.global_block_h * h / 100; + block_x1 = block_x - block_w / 2; + block_y1 = block_y - block_h / 2; + block_x2 = block_x + block_w / 2; + block_y2 = block_y + block_h / 2; + search_w = config.global_range_w * w / 100; + search_h = config.global_range_h * h / 100; + search_x1 = block_x1 - search_w / 2; + search_y1 = block_y1 - search_h / 2; + search_x2 = block_x2 + search_w / 2; + search_y2 = block_y2 + search_h / 2; + +// printf("MotionCVMain::draw_vectors %d %d %d %d %d %d %d %d %d %d %d %d\n", +// global_x1, +// global_y1, +// block_w, +// block_h, +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// search_x1, +// search_y1, +// search_x2, +// search_y2); + + clamp_scan(w, + h, + &block_x1, + &block_y1, + &block_x2, + &block_y2, + &search_x1, + &search_y1, + &search_x2, + &search_y2, + 1); + +// Vector + draw_arrow(frame, global_x1, global_y1, global_x2, global_y2); + +// Macroblock + draw_line(frame, block_x1, block_y1, block_x2, block_y1); + draw_line(frame, block_x2, block_y1, block_x2, block_y2); + draw_line(frame, block_x2, block_y2, block_x1, block_y2); + draw_line(frame, block_x1, block_y2, block_x1, block_y1); + + +// Search area + draw_line(frame, search_x1, search_y1, search_x2, search_y1); + draw_line(frame, search_x2, search_y1, search_x2, search_y2); + draw_line(frame, search_x2, search_y2, search_x1, search_y2); + draw_line(frame, search_x1, search_y2, search_x1, search_y1); + +// Block should be endpoint of motion + if(config.rotate) + { + block_x = global_x2; + block_y = global_y2; + } + } + else + { + block_x = (int64_t)(config.block_x * w / 100); + block_y = (int64_t)(config.block_y * h / 100); + } + + block_w = config.rotation_block_w * w / 100; + block_h = config.rotation_block_h * h / 100; + if(config.rotate) + { + float angle = total_angle * 2 * M_PI / 360; + double base_angle1 = atan((float)block_h / block_w); + double base_angle2 = atan((float)block_w / block_h); + double target_angle1 = base_angle1 + angle; + double target_angle2 = base_angle2 + angle; + double radius = sqrt(block_w * block_w + block_h * block_h) / 2; + block_x1 = (int)(block_x - cos(target_angle1) * radius); + block_y1 = (int)(block_y - sin(target_angle1) * radius); + block_x2 = (int)(block_x + sin(target_angle2) * radius); + block_y2 = (int)(block_y - cos(target_angle2) * radius); + block_x3 = (int)(block_x - sin(target_angle2) * radius); + block_y3 = (int)(block_y + cos(target_angle2) * radius); + block_x4 = (int)(block_x + cos(target_angle1) * radius); + block_y4 = (int)(block_y + sin(target_angle1) * radius); + + draw_line(frame, block_x1, block_y1, block_x2, block_y2); + draw_line(frame, block_x2, block_y2, block_x4, block_y4); + draw_line(frame, block_x4, block_y4, block_x3, block_y3); + draw_line(frame, block_x3, block_y3, block_x1, block_y1); + + +// Center + if(!config.global) + { + draw_line(frame, block_x, block_y - 5, block_x, block_y + 6); + draw_line(frame, block_x - 5, block_y, block_x + 6, block_y); + } + } +} + + + +void MotionCVMain::draw_pixel(VFrame *frame, int x, int y) +{ + if(!(x >= 0 && y >= 0 && x < frame->get_w() && y < frame->get_h())) return; + +#define DRAW_PIXEL(x, y, components, do_yuv, max, type) \ +{ \ + type **rows = (type**)frame->get_rows(); \ + rows[y][x * components] = max - rows[y][x * components]; \ + if(!do_yuv) \ + { \ + rows[y][x * components + 1] = max - rows[y][x * components + 1]; \ + rows[y][x * components + 2] = max - rows[y][x * components + 2]; \ + } \ + else \ + { \ + rows[y][x * components + 1] = (max / 2 + 1) - rows[y][x * components + 1]; \ + rows[y][x * components + 2] = (max / 2 + 1) - rows[y][x * components + 2]; \ + } \ + if(components == 4) \ + rows[y][x * components + 3] = max; \ +} + + + switch(frame->get_color_model()) + { + case BC_RGB888: + DRAW_PIXEL(x, y, 3, 0, 0xff, unsigned char); + break; + case BC_RGBA8888: + DRAW_PIXEL(x, y, 4, 0, 0xff, unsigned char); + break; + case BC_RGB_FLOAT: + DRAW_PIXEL(x, y, 3, 0, 1.0, float); + break; + case BC_RGBA_FLOAT: + DRAW_PIXEL(x, y, 4, 0, 1.0, float); + break; + case BC_YUV888: + DRAW_PIXEL(x, y, 3, 1, 0xff, unsigned char); + break; + case BC_YUVA8888: + DRAW_PIXEL(x, y, 4, 1, 0xff, unsigned char); + break; + case BC_RGB161616: + DRAW_PIXEL(x, y, 3, 0, 0xffff, uint16_t); + break; + case BC_YUV161616: + DRAW_PIXEL(x, y, 3, 1, 0xffff, uint16_t); + break; + case BC_RGBA16161616: + DRAW_PIXEL(x, y, 4, 0, 0xffff, uint16_t); + break; + case BC_YUVA16161616: + DRAW_PIXEL(x, y, 4, 1, 0xffff, uint16_t); + break; + } +} + + +void MotionCVMain::draw_line(VFrame *frame, int x1, int y1, int x2, int y2) +{ + int w = labs(x2 - x1); + int h = labs(y2 - y1); +//printf("MotionCVMain::draw_line 1 %d %d %d %d\n", x1, y1, x2, y2); + + if(!w && !h) + { + draw_pixel(frame, x1, y1); + } + else + if(w > h) + { +// Flip coordinates so x1 < x2 + if(x2 < x1) + { + y2 ^= y1; + y1 ^= y2; + y2 ^= y1; + x1 ^= x2; + x2 ^= x1; + x1 ^= x2; + } + int numerator = y2 - y1; + int denominator = x2 - x1; + for(int i = x1; i < x2; i++) + { + int y = y1 + (int64_t)(i - x1) * (int64_t)numerator / (int64_t)denominator; + draw_pixel(frame, i, y); + } + } + else + { +// Flip coordinates so y1 < y2 + if(y2 < y1) + { + y2 ^= y1; + y1 ^= y2; + y2 ^= y1; + x1 ^= x2; + x2 ^= x1; + x1 ^= x2; + } + int numerator = x2 - x1; + int denominator = y2 - y1; + for(int i = y1; i < y2; i++) + { + int x = x1 + (int64_t)(i - y1) * (int64_t)numerator / (int64_t)denominator; + draw_pixel(frame, x, i); + } + } +//printf("MotionCVMain::draw_line 2\n"); +} + +#define ARROW_SIZE 10 +void MotionCVMain::draw_arrow(VFrame *frame, int x1, int y1, int x2, int y2) +{ + double angle = atan((float)(y2 - y1) / (float)(x2 - x1)); + double angle1 = angle + (float)145 / 360 * 2 * 3.14159265; + double angle2 = angle - (float)145 / 360 * 2 * 3.14159265; + int x3; + int y3; + int x4; + int y4; + if(x2 < x1) + { + x3 = x2 - (int)(ARROW_SIZE * cos(angle1)); + y3 = y2 - (int)(ARROW_SIZE * sin(angle1)); + x4 = x2 - (int)(ARROW_SIZE * cos(angle2)); + y4 = y2 - (int)(ARROW_SIZE * sin(angle2)); + } + else + { + x3 = x2 + (int)(ARROW_SIZE * cos(angle1)); + y3 = y2 + (int)(ARROW_SIZE * sin(angle1)); + x4 = x2 + (int)(ARROW_SIZE * cos(angle2)); + y4 = y2 + (int)(ARROW_SIZE * sin(angle2)); + } + +// Main vector + draw_line(frame, x1, y1, x2, y2); +// draw_line(frame, x1, y1 + 1, x2, y2 + 1); + +// Arrow line + if(abs(y2 - y1) || abs(x2 - x1)) draw_line(frame, x2, y2, x3, y3); +// draw_line(frame, x2, y2 + 1, x3, y3 + 1); +// Arrow line + if(abs(y2 - y1) || abs(x2 - x1)) draw_line(frame, x2, y2, x4, y4); +// draw_line(frame, x2, y2 + 1, x4, y4 + 1); +} + + + + +#define ABS_DIFF(type, temp_type, multiplier, components) \ +{ \ + temp_type result_temp = 0; \ + for(int i = 0; i < h; i++) \ + { \ + type *prev_row = (type*)prev_ptr; \ + type *current_row = (type*)current_ptr; \ + for(int j = 0; j < w; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + temp_type difference; \ + difference = *prev_row++ - *current_row++; \ + if(difference < 0) \ + result_temp -= difference; \ + else \ + result_temp += difference; \ + } \ + if(components == 4) \ + { \ + prev_row++; \ + current_row++; \ + } \ + } \ + prev_ptr += row_bytes; \ + current_ptr += row_bytes; \ + } \ + result = (int64_t)(result_temp * multiplier); \ +} + +int64_t MotionCVMain::abs_diff(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model) +{ + int64_t result = 0; + switch(color_model) + { + case BC_RGB888: + ABS_DIFF(unsigned char, int64_t, 1, 3) + break; + case BC_RGBA8888: + ABS_DIFF(unsigned char, int64_t, 1, 4) + break; + case BC_RGB_FLOAT: + ABS_DIFF(float, double, 0x10000, 3) + break; + case BC_RGBA_FLOAT: + ABS_DIFF(float, double, 0x10000, 4) + break; + case BC_YUV888: + ABS_DIFF(unsigned char, int64_t, 1, 3) + break; + case BC_YUVA8888: + ABS_DIFF(unsigned char, int64_t, 1, 4) + break; + case BC_YUV161616: + ABS_DIFF(uint16_t, int64_t, 1, 3) + break; + case BC_YUVA16161616: + ABS_DIFF(uint16_t, int64_t, 1, 4) + break; + } + return result; +} + + + +#define ABS_DIFF_SUB(type, temp_type, multiplier, components) \ +{ \ + temp_type result_temp = 0; \ + temp_type y2_fraction = sub_y * 0x100 / OVERSAMPLE; \ + temp_type y1_fraction = 0x100 - y2_fraction; \ + temp_type x2_fraction = sub_x * 0x100 / OVERSAMPLE; \ + temp_type x1_fraction = 0x100 - x2_fraction; \ + for(int i = 0; i < h_sub; i++) \ + { \ + type *prev_row1 = (type*)prev_ptr; \ + type *prev_row2 = (type*)prev_ptr + components; \ + type *prev_row3 = (type*)(prev_ptr + row_bytes); \ + type *prev_row4 = (type*)(prev_ptr + row_bytes) + components; \ + type *current_row = (type*)current_ptr; \ + for(int j = 0; j < w_sub; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + temp_type difference; \ + temp_type prev_value = \ + (*prev_row1++ * x1_fraction * y1_fraction + \ + *prev_row2++ * x2_fraction * y1_fraction + \ + *prev_row3++ * x1_fraction * y2_fraction + \ + *prev_row4++ * x2_fraction * y2_fraction) / \ + 0x100 / 0x100; \ + temp_type current_value = *current_row++; \ + difference = prev_value - current_value; \ + if(difference < 0) \ + result_temp -= difference; \ + else \ + result_temp += difference; \ + } \ + \ + if(components == 4) \ + { \ + prev_row1++; \ + prev_row2++; \ + prev_row3++; \ + prev_row4++; \ + current_row++; \ + } \ + } \ + prev_ptr += row_bytes; \ + current_ptr += row_bytes; \ + } \ + result = (int64_t)(result_temp * multiplier); \ +} + + + + +int64_t MotionCVMain::abs_diff_sub(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model, + int sub_x, + int sub_y) +{ + int h_sub = h - 1; + int w_sub = w - 1; + int64_t result = 0; + + switch(color_model) + { + case BC_RGB888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) + break; + case BC_RGBA8888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) + break; + case BC_RGB_FLOAT: + ABS_DIFF_SUB(float, double, 0x10000, 3) + break; + case BC_RGBA_FLOAT: + ABS_DIFF_SUB(float, double, 0x10000, 4) + break; + case BC_YUV888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) + break; + case BC_YUVA8888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) + break; + case BC_YUV161616: + ABS_DIFF_SUB(uint16_t, int64_t, 1, 3) + break; + case BC_YUVA16161616: + ABS_DIFF_SUB(uint16_t, int64_t, 1, 4) + break; + } + return result; +} + +int MotionCVMain::get_line_key(const char *filename, int64_t key, char *line, int len) +{ + if( active_fp && strcmp(active_file, filename) ) { + fclose(active_fp); active_fp = 0; active_file[0] = 0; + } + if( !active_fp ) { + if( !(active_fp = fopen(filename, "r")) ) { + perror("open motion file"); + fprintf(stderr,"err reading key %jd\n", key); + return -1; + } + strcpy(active_file, filename); + tracking_frame = -1; + } + int64_t recd = 0; + if( fgets(line, len, active_fp) && (recd=strtol(line,0,0)) == key ) + return 0; +// binary search file + fseek(active_fp, 0, SEEK_END); + int64_t l = -1, r = ftell(active_fp); + while( (r-l) > 1 ) { + int64_t m = (l+r) / 2; + fseek(active_fp, m, SEEK_SET); + if( m > 0 && !fgets(line, len, active_fp) ) { + fprintf(stderr,"err reading key %jd\n", key); + return -1; + } + if( fgets(line, len, active_fp) ) { + recd = strtol(line,0,0); + if( recd == key ) return 0; + if( recd < key ) { l = m; continue; } + } + r = m; + } + return 1; +} + + + +MotionCVScanPackage::MotionCVScanPackage() + : LoadPackage() +{ + valid = 1; +} + + +MotionCVScanUnit::MotionCVScanUnit(MotionCVScan *server, + MotionCVMain *plugin) + : LoadClient(server) +{ + this->plugin = plugin; + this->server = server; + cache_lock = new Mutex("MotionCVScanUnit::cache_lock"); +} + +MotionCVScanUnit::~MotionCVScanUnit() +{ + delete cache_lock; +} + + + +void MotionCVScanUnit::process_package(LoadPackage *package) +{ + MotionCVScanPackage *pkg = (MotionCVScanPackage*)package; + //int w = server->current_frame->get_w(); + //int h = server->current_frame->get_h(); + int color_model = server->current_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = server->current_frame->get_bytes_per_line(); + +// Single pixel + if(!server->subpixel) + { + int search_x = pkg->scan_x1 + (pkg->pixel % (pkg->scan_x2 - pkg->scan_x1)); + int search_y = pkg->scan_y1 + (pkg->pixel / (pkg->scan_x2 - pkg->scan_x1)); + +// Try cache + pkg->difference1 = server->get_cache(search_x, search_y); + if(pkg->difference1 < 0) + { +//printf("MotionCVScanUnit::process_package 1 %d %d\n", +//search_x, search_y, pkg->block_x2 - pkg->block_x1, pkg->block_y2 - pkg->block_y1); +// Pointers to first pixel in each block + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + search_y] + + search_x * pixel_size; + unsigned char *current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; +// Scan block + pkg->difference1 = plugin->abs_diff(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model); +//printf("MotionCVScanUnit::process_package 2\n"); + server->put_cache(search_x, search_y, pkg->difference1); + } + } + else +// Sub pixel + { + int sub_x = pkg->pixel % (OVERSAMPLE * 2 - 1) + 1; + int sub_y = pkg->pixel / (OVERSAMPLE * 2 - 1) + 1; + + if(plugin->config.horizontal_only) + { + sub_y = 0; + } + + if(plugin->config.vertical_only) + { + sub_x = 0; + } + + int search_x = pkg->scan_x1 + sub_x / OVERSAMPLE; + int search_y = pkg->scan_y1 + sub_y / OVERSAMPLE; + sub_x %= OVERSAMPLE; + sub_y %= OVERSAMPLE; + + + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + search_y] + + search_x * pixel_size; + unsigned char *current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; + +// With subpixel, there are two ways to compare each position, one by shifting +// the previous frame and two by shifting the current frame. + pkg->difference1 = plugin->abs_diff_sub(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + sub_x, + sub_y); + pkg->difference2 = plugin->abs_diff_sub(current_ptr, + prev_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + sub_x, + sub_y); +// printf("MotionCVScanUnit::process_package sub_x=%d sub_y=%d search_x=%d search_y=%d diff1=%lld diff2=%lld\n", +// sub_x, +// sub_y, +// search_x, +// search_y, +// pkg->difference1, +// pkg->difference2); + } + + + + +} + + + + + + + + + + +int64_t MotionCVScanUnit::get_cache(int x, int y) +{ + int64_t result = -1; + cache_lock->lock("MotionCVScanUnit::get_cache"); + for(int i = 0; i < cache.total; i++) + { + MotionCVScanCache *ptr = cache.values[i]; + if(ptr->x == x && ptr->y == y) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void MotionCVScanUnit::put_cache(int x, int y, int64_t difference) +{ + MotionCVScanCache *ptr = new MotionCVScanCache(x, y, difference); + cache_lock->lock("MotionCVScanUnit::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + + + + + + + + + +MotionCVScan::MotionCVScan(MotionCVMain *plugin, + int total_clients, + int total_packages) + : LoadServer( +//1, 1 +total_clients, total_packages +) +{ + this->plugin = plugin; + cache_lock = new Mutex("MotionCVScan::cache_lock"); +} + +MotionCVScan::~MotionCVScan() +{ + delete cache_lock; +} + + +void MotionCVScan::init_packages() +{ +// Set package coords + for(int i = 0; i < get_total_packages(); i++) + { + MotionCVScanPackage *pkg = (MotionCVScanPackage*)get_package(i); + + pkg->block_x1 = block_x1; + pkg->block_x2 = block_x2; + pkg->block_y1 = block_y1; + pkg->block_y2 = block_y2; + pkg->scan_x1 = scan_x1; + pkg->scan_x2 = scan_x2; + pkg->scan_y1 = scan_y1; + pkg->scan_y2 = scan_y2; + pkg->pixel = (int64_t)i * (int64_t)total_pixels / (int64_t)total_steps; + pkg->difference1 = 0; + pkg->difference2 = 0; + pkg->dx = 0; + pkg->dy = 0; + pkg->valid = 1; + } +} + +LoadClient* MotionCVScan::new_client() +{ + return new MotionCVScanUnit(this, plugin); +} + +LoadPackage* MotionCVScan::new_package() +{ + return new MotionCVScanPackage; +} + + +void MotionCVScan::scan_frame(VFrame *previous_frame, + VFrame *current_frame) +{ + this->previous_frame = previous_frame; + this->current_frame = current_frame; + subpixel = 0; + + cache.remove_all_objects(); + + +// Single macroblock + int w = current_frame->get_w(); + int h = current_frame->get_h(); + +// Initial search parameters + int scan_w = w * plugin->config.global_range_w / 100; + int scan_h = h * plugin->config.global_range_h / 100; + int block_w = w * plugin->config.global_block_w / 100; + int block_h = h * plugin->config.global_block_h / 100; + +// Location of block in previous frame + block_x1 = (int)(w * plugin->config.block_x / 100 - block_w / 2); + block_y1 = (int)(h * plugin->config.block_y / 100 - block_h / 2); + block_x2 = (int)(w * plugin->config.block_x / 100 + block_w / 2); + block_y2 = (int)(h * plugin->config.block_y / 100 + block_h / 2); + +// Offset to location of previous block. This offset needn't be very accurate +// since it's the offset of the previous image and current image we want. + if(plugin->config.mode3 == MotionCVConfig::TRACK_PREVIOUS) + { + block_x1 += plugin->total_dx / OVERSAMPLE; + block_y1 += plugin->total_dy / OVERSAMPLE; + block_x2 += plugin->total_dx / OVERSAMPLE; + block_y2 += plugin->total_dy / OVERSAMPLE; + } + + skip = 0; + + switch(plugin->config.mode2) + { +// Don't calculate + case MotionCVConfig::NO_CALCULATE: + dx_result = 0; + dy_result = 0; + skip = 1; + break; + + case MotionCVConfig::LOAD: + { + dx_result = plugin->load_dx; + dy_result = plugin->load_dy; + skip = 1; + break; + } + +// Scan from scratch + default: + skip = 0; + break; + } + +// Perform scan + if(!skip) + { +// Location of block in current frame + int x_result = block_x1; + int y_result = block_y1; + +// printf("MotionCVScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", +// block_x1 + block_w / 2, +// block_y1 + block_h / 2, +// block_w, +// block_h, +// block_x1, +// block_y1, +// block_x2, +// block_y2); + + while(1) + { + scan_x1 = x_result - scan_w / 2; + scan_y1 = y_result - scan_h / 2; + scan_x2 = x_result + scan_w / 2; + scan_y2 = y_result + scan_h / 2; + + + +// Zero out requested values + if(plugin->config.horizontal_only) + { + scan_y1 = block_y1; + scan_y2 = block_y1 + 1; + } + if(plugin->config.vertical_only) + { + scan_x1 = block_x1; + scan_x2 = block_x1 + 1; + } + +// printf("MotionCVScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2); +// Clamp the block coords before the scan so we get useful scan coords. + MotionCVMain::clamp_scan(w, + h, + &block_x1, + &block_y1, + &block_x2, + &block_y2, + &scan_x1, + &scan_y1, + &scan_x2, + &scan_y2, + 0); +// printf("MotionCVScan::scan_frame 1\n block_x1=%d block_y1=%d block_x2=%d block_y2=%d\n scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d\n x_result=%d y_result=%d\n", +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2, +// x_result, +// y_result); + + +// Give up if invalid coords. + if(scan_y2 <= scan_y1 || + scan_x2 <= scan_x1 || + block_x2 <= block_x1 || + block_y2 <= block_y1) + break; + +// For subpixel, the top row and left column are skipped + if(subpixel) + { + if(plugin->config.horizontal_only || + plugin->config.vertical_only) + { + total_pixels = 4 * OVERSAMPLE * OVERSAMPLE - 4 * OVERSAMPLE; + } + else + { + total_pixels = 4 * OVERSAMPLE; + } + + total_steps = total_pixels; + + set_package_count(total_steps); + process_packages(); + +// Get least difference + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + MotionCVScanPackage *pkg = (MotionCVScanPackage*)get_package(i); + if(pkg->difference1 < min_difference || min_difference == -1) + { + min_difference = pkg->difference1; + + if(plugin->config.vertical_only) + x_result = scan_x1 * OVERSAMPLE; + else + x_result = scan_x1 * OVERSAMPLE + + (pkg->pixel % (OVERSAMPLE * 2 - 1)) + 1; + + if(plugin->config.horizontal_only) + y_result = scan_y1 * OVERSAMPLE; + else + y_result = scan_y1 * OVERSAMPLE + + (pkg->pixel / (OVERSAMPLE * 2 - 1)) + 1; + + +// Fill in results + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; + } + + if(pkg->difference2 < min_difference) + { + min_difference = pkg->difference2; + + if(plugin->config.vertical_only) + x_result = scan_x1 * OVERSAMPLE; + else + x_result = scan_x2 * OVERSAMPLE - + ((pkg->pixel % (OVERSAMPLE * 2 - 1)) + 1); + + if(plugin->config.horizontal_only) + y_result = scan_y1 * OVERSAMPLE; + else + y_result = scan_y2 * OVERSAMPLE - + ((pkg->pixel / (OVERSAMPLE * 2 - 1)) + 1); + + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; + } + } + +//printf("MotionCVScan::scan_frame 1 %d %d %d %d\n", block_x1, block_y1, x_result, y_result); + break; + } + else + { + total_pixels = (scan_x2 - scan_x1) * (scan_y2 - scan_y1); + total_steps = MIN(plugin->config.global_positions, total_pixels); + + set_package_count(total_steps); + process_packages(); + +// Get least difference + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + MotionCVScanPackage *pkg = (MotionCVScanPackage*)get_package(i); + if(pkg->difference1 < min_difference || min_difference == -1) + { + min_difference = pkg->difference1; + x_result = scan_x1 + (pkg->pixel % (scan_x2 - scan_x1)); + y_result = scan_y1 + (pkg->pixel / (scan_x2 - scan_x1)); + x_result *= OVERSAMPLE; + y_result *= OVERSAMPLE; + } + } + +// printf("MotionCVScan::scan_frame 10 total_steps=%d total_pixels=%d subpixel=%d\n", +// total_steps, +// total_pixels, +// subpixel); +// +// printf(" scan w=%d h=%d scan x1=%d y1=%d x2=%d y2=%d\n", +// scan_w, +// scan_h, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2); +// +// printf("MotionCVScan::scan_frame 2 block x1=%d y1=%d x2=%d y2=%d result x=%.2f y=%.2f\n", +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// (float)x_result / 4, +// (float)y_result / 4); + + +// If a new search is required, rescale results back to pixels. + if(total_steps >= total_pixels) + { +// Single pixel accuracy reached. Now do exhaustive subpixel search. + if(plugin->config.mode1 == MotionCVConfig::STABILIZE || + plugin->config.mode1 == MotionCVConfig::TRACK || + plugin->config.mode1 == MotionCVConfig::NOTHING) + { + x_result /= OVERSAMPLE; + y_result /= OVERSAMPLE; + scan_w = 2; + scan_h = 2; + subpixel = 1; + } + else + { +// Fill in results and quit + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; + break; + } + } + else +// Reduce scan area and try again + { + scan_w = (scan_x2 - scan_x1) / 2; + scan_h = (scan_y2 - scan_y1) / 2; + x_result /= OVERSAMPLE; + y_result /= OVERSAMPLE; + } + } + } + + // Add offsets from the "tracked single frame" + dx_result = plugin->dx_offset - dx_result; + dy_result = plugin->dy_offset - dy_result; + + if(plugin->config.mode2 == MotionCVConfig::SAVE) + { + plugin->save_dx = dx_result; + plugin->save_dy = dy_result; + } + } + +#ifdef DEBUG +printf("MotionCVScan::scan_frame 10 dx=%.2f dy=%.2f\n", +(float)this->dx_result / OVERSAMPLE, +(float)this->dy_result / OVERSAMPLE); +#endif +} + + + + + + + + + + + + + + + + + +int64_t MotionCVScan::get_cache(int x, int y) +{ + int64_t result = -1; + cache_lock->lock("MotionCVScan::get_cache"); + for(int i = 0; i < cache.total; i++) + { + MotionCVScanCache *ptr = cache.values[i]; + if(ptr->x == x && ptr->y == y) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void MotionCVScan::put_cache(int x, int y, int64_t difference) +{ + MotionCVScanCache *ptr = new MotionCVScanCache(x, y, difference); + cache_lock->lock("MotionCVScan::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + + + +MotionCVScanCache::MotionCVScanCache(int x, int y, int64_t difference) +{ + this->x = x; + this->y = y; + this->difference = difference; +} + + + + + + + + + + + + + + +RotateCVScanPackage::RotateCVScanPackage() +{ +} + + +RotateCVScanUnit::RotateCVScanUnit(RotateCVScan *server, MotionCVMain *plugin) + : LoadClient(server) +{ + this->server = server; + this->plugin = plugin; + rotater = 0; + temp = 0; +} + +RotateCVScanUnit::~RotateCVScanUnit() +{ + delete rotater; + delete temp; +} + +void RotateCVScanUnit::process_package(LoadPackage *package) +{ + if(server->skip) return; + RotateCVScanPackage *pkg = (RotateCVScanPackage*)package; + + if((pkg->difference = server->get_cache(pkg->angle)) < 0) + { +//printf("RotateCVScanUnit::process_package 1\n"); + int color_model = server->previous_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = server->previous_frame->get_bytes_per_line(); + + if(!rotater) + rotater = new AffineEngine(1, 1); + if(!temp) temp = new VFrame( + server->previous_frame->get_w(), + server->previous_frame->get_h(), + color_model); + + +// RotateCV original block size + rotater->set_viewport(server->block_x1, + server->block_y1, + server->block_x2 - server->block_x1, + server->block_y2 - server->block_y1); + rotater->set_pivot(server->block_x, server->block_y); +//pkg->angle = 2; + rotater->rotate(temp, + server->previous_frame, + pkg->angle); +// Clamp coordinates + int x1 = server->scan_x; + int y1 = server->scan_y; + int x2 = x1 + server->scan_w; + int y2 = y1 + server->scan_h; + x2 = MIN(temp->get_w(), x2); + y2 = MIN(temp->get_h(), y2); + x2 = MIN(server->current_frame->get_w(), x2); + y2 = MIN(server->current_frame->get_h(), y2); + x1 = MAX(0, x1); + y1 = MAX(0, y1); + + if(x2 > x1 && y2 > y1) + { + pkg->difference = plugin->abs_diff( + temp->get_rows()[y1] + x1 * pixel_size, + server->current_frame->get_rows()[y1] + x1 * pixel_size, + row_bytes, + x2 - x1, + y2 - y1, + color_model); +//printf("RotateCVScanUnit::process_package %d\n", __LINE__); + server->put_cache(pkg->angle, pkg->difference); + } + +// printf("RotateCVScanUnit::process_package 10 x=%d y=%d w=%d h=%d block_x=%d block_y=%d angle=%f scan_w=%d scan_h=%d diff=%lld\n", +// server->block_x1, +// server->block_y1, +// server->block_x2 - server->block_x1, +// server->block_y2 - server->block_y1, +// server->block_x, +// server->block_y, +// pkg->angle, +// server->scan_w, +// server->scan_h, +// pkg->difference); + } +} + + + + + + + + + + + + + + + + + + + + + + +RotateCVScan::RotateCVScan(MotionCVMain *plugin, + int total_clients, + int total_packages) + : LoadServer( +//1, 1 +total_clients, total_packages +) +{ + this->plugin = plugin; + cache_lock = new Mutex("RotateCVScan::cache_lock"); +} + + +RotateCVScan::~RotateCVScan() +{ + delete cache_lock; +} + +void RotateCVScan::init_packages() +{ + for(int i = 0; i < get_total_packages(); i++) + { + RotateCVScanPackage *pkg = (RotateCVScanPackage*)get_package(i); + pkg->angle = i * + (scan_angle2 - scan_angle1) / + (total_steps - 1) + + scan_angle1; + } +} + +LoadClient* RotateCVScan::new_client() +{ + return new RotateCVScanUnit(this, plugin); +} + +LoadPackage* RotateCVScan::new_package() +{ + return new RotateCVScanPackage; +} + + +float RotateCVScan::scan_frame(VFrame *previous_frame, + VFrame *current_frame, + int block_x, + int block_y) +{ + skip = 0; + this->block_x = block_x; + this->block_y = block_y; + + switch(plugin->config.mode2) + { + case MotionCVConfig::NO_CALCULATE: + result = 0; + skip = 1; + break; + + case MotionCVConfig::LOAD: + { + result = plugin->load_dt; + skip = 1; + break; + } + } + + + this->previous_frame = previous_frame; + this->current_frame = current_frame; + int w = current_frame->get_w(); + int h = current_frame->get_h(); + int block_w = w * plugin->config.rotation_block_w / 100; + int block_h = h * plugin->config.rotation_block_h / 100; + + if(this->block_x - block_w / 2 < 0) block_w = this->block_x * 2; + if(this->block_y - block_h / 2 < 0) block_h = this->block_y * 2; + if(this->block_x + block_w / 2 > w) block_w = (w - this->block_x) * 2; + if(this->block_y + block_h / 2 > h) block_h = (h - this->block_y) * 2; + + block_x1 = this->block_x - block_w / 2; + block_x2 = this->block_x + block_w / 2; + block_y1 = this->block_y - block_h / 2; + block_y2 = this->block_y + block_h / 2; + + +// Calculate the maximum area available to scan after rotation. +// Must be calculated from the starting range because of cache. +// Get coords of rectangle after rotation. + double center_x = this->block_x; + double center_y = this->block_y; + double max_angle = plugin->config.rotation_range; + double base_angle1 = atan((float)block_h / block_w); + double base_angle2 = atan((float)block_w / block_h); + double target_angle1 = base_angle1 + max_angle * 2 * M_PI / 360; + double target_angle2 = base_angle2 + max_angle * 2 * M_PI / 360; + double radius = sqrt(block_w * block_w + block_h * block_h) / 2; + double x1 = center_x - cos(target_angle1) * radius; + double y1 = center_y - sin(target_angle1) * radius; + double x2 = center_x + sin(target_angle2) * radius; + double y2 = center_y - cos(target_angle2) * radius; + double x3 = center_x - sin(target_angle2) * radius; + double y3 = center_y + cos(target_angle2) * radius; + +// Track top edge to find greatest area. + double max_area1 = 0; + //double max_x1 = 0; + double max_y1 = 0; + for(double x = x1; x < x2; x++) + { + double y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); + if(x >= center_x && x < block_x2 && y >= block_y1 && y < center_y) + { + double area = fabs(x - center_x) * fabs(y - center_y); + if(area > max_area1) + { + max_area1 = area; + //max_x1 = x; + max_y1 = y; + } + } + } + +// Track left edge to find greatest area. + double max_area2 = 0; + double max_x2 = 0; + //double max_y2 = 0; + for(double y = y1; y < y3; y++) + { + double x = x1 + (x3 - x1) * (y - y1) / (y3 - y1); + if(x >= block_x1 && x < center_x && y >= block_y1 && y < center_y) + { + double area = fabs(x - center_x) * fabs(y - center_y); + if(area > max_area2) + { + max_area2 = area; + max_x2 = x; + //max_y2 = y; + } + } + } + + double max_x, max_y; + max_x = max_x2; + max_y = max_y1; + +// Get reduced scan coords + scan_w = (int)(fabs(max_x - center_x) * 2); + scan_h = (int)(fabs(max_y - center_y) * 2); + scan_x = (int)(center_x - scan_w / 2); + scan_y = (int)(center_y - scan_h / 2); +// printf("RotateCVScan::scan_frame center=%d,%d scan=%d,%d %dx%d\n", +// this->block_x, this->block_y, scan_x, scan_y, scan_w, scan_h); +// printf(" angle_range=%f block= %d,%d,%d,%d\n", max_angle, block_x1, block_y1, block_x2, block_y2); + +// Determine min angle from size of block + double angle1 = atan((double)block_h / block_w); + double angle2 = atan((double)(block_h - 1) / (block_w + 1)); + double min_angle = fabs(angle2 - angle1) / OVERSAMPLE; + min_angle = MAX(min_angle, MIN_ANGLE); + +#ifdef DEBUG +printf("RotateCVScan::scan_frame min_angle=%f\n", min_angle * 360 / 2 / M_PI); +#endif + + cache.remove_all_objects(); + if(!skip) + { +// Initial search range + float angle_range = (float)plugin->config.rotation_range; + result = 0; + total_steps = plugin->config.rotate_positions; + + + while(angle_range >= min_angle * total_steps) + { + scan_angle1 = result - angle_range; + scan_angle2 = result + angle_range; + + + set_package_count(total_steps); +//set_package_count(1); + process_packages(); + + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + RotateCVScanPackage *pkg = (RotateCVScanPackage*)get_package(i); + if(pkg->difference < min_difference || min_difference == -1) + { + min_difference = pkg->difference; + result = pkg->angle; + } +//break; + } + + angle_range /= 2; + +//break; + } + + if(plugin->config.mode2 == MotionCVConfig::SAVE) { + plugin->save_dt = result; + } + } + +#ifdef DEBUG +printf("RotateCVScan::scan_frame 10 angle=%f\n", result); +#endif + + return result; +} + +int64_t RotateCVScan::get_cache(float angle) +{ + int64_t result = -1; + cache_lock->lock("RotateCVScan::get_cache"); + for(int i = 0; i < cache.total; i++) + { + RotateCVScanCache *ptr = cache.values[i]; + if(fabs(ptr->angle - angle) <= MIN_ANGLE) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void RotateCVScan::put_cache(float angle, int64_t difference) +{ + RotateCVScanCache *ptr = new RotateCVScanCache(angle, difference); + cache_lock->lock("RotateCVScan::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + + + + + + + +RotateCVScanCache::RotateCVScanCache(float angle, int64_t difference) +{ + this->angle = angle; + this->difference = difference; +} + + + diff --git a/cinelerra-5.1/plugins/motion-cv/motion-cv.C.orig b/cinelerra-5.1/plugins/motion-cv/motion-cv.C.orig new file mode 100644 index 00000000..a5eb1912 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/motion-cv.C.orig @@ -0,0 +1,2731 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 "affine.h" +#include "bcdisplayinfo.h" +#include "clip.h" +#include "bchash.h" +#include "bcsignals.h" +#include "filexml.h" +#include "keyframe.h" +#include "language.h" +#include "motion-cv.h" +#include "motionwindow-cv.h" +#include "mutex.h" +#include "overlayframe.h" +#include "rotateframe.h" +#include "transportque.h" + + +#include +#include + +REGISTER_PLUGIN(MotionCVMain) + +//#undef DEBUG + +#ifndef DEBUG +#define DEBUG +#endif + + +MotionCVConfig::MotionCVConfig() +{ + global_range_w = 5; + global_range_h = 5; + rotation_range = 5; + block_count = 1; + global_block_w = MIN_BLOCK; + global_block_h = MIN_BLOCK; + rotation_block_w = MIN_BLOCK; + rotation_block_h = MIN_BLOCK; + block_x = 50; + block_y = 50; + global_positions = 256; + rotate_positions = 4; + magnitude = 100; + return_speed = 0; + mode1 = STABILIZE; + global = 1; + rotate = 1; + addtrackedframeoffset = 0; + mode2 = RECALCULATE; + draw_vectors = 1; + mode3 = MotionCVConfig::TRACK_SINGLE; + track_frame = 0; + bottom_is_master = 1; + horizontal_only = 0; + vertical_only = 0; +} + +void MotionCVConfig::boundaries() +{ + CLAMP(global_range_w, MIN_RADIUS, MAX_RADIUS); + CLAMP(global_range_h, MIN_RADIUS, MAX_RADIUS); + CLAMP(rotation_range, MIN_ROTATION, MAX_ROTATION); + CLAMP(block_count, MIN_BLOCKS, MAX_BLOCKS); + CLAMP(global_block_w, MIN_BLOCK, MAX_BLOCK); + CLAMP(global_block_h, MIN_BLOCK, MAX_BLOCK); + CLAMP(rotation_block_w, MIN_BLOCK, MAX_BLOCK); + CLAMP(rotation_block_h, MIN_BLOCK, MAX_BLOCK); +} + +int MotionCVConfig::equivalent(MotionCVConfig &that) +{ + return global_range_w == that.global_range_w && + global_range_h == that.global_range_h && + rotation_range == that.rotation_range && + mode1 == that.mode1 && + global == that.global && + rotate == that.rotate && + addtrackedframeoffset == that.addtrackedframeoffset && + draw_vectors == that.draw_vectors && + block_count == that.block_count && + global_block_w == that.global_block_w && + global_block_h == that.global_block_h && + rotation_block_w == that.rotation_block_w && + rotation_block_h == that.rotation_block_h && + EQUIV(block_x, that.block_x) && + EQUIV(block_y, that.block_y) && + global_positions == that.global_positions && + rotate_positions == that.rotate_positions && + magnitude == that.magnitude && + return_speed == that.return_speed && + mode3 == that.mode3 && + track_frame == that.track_frame && + bottom_is_master == that.bottom_is_master && + horizontal_only == that.horizontal_only && + vertical_only == that.vertical_only; +} + +void MotionCVConfig::copy_from(MotionCVConfig &that) +{ + global_range_w = that.global_range_w; + global_range_h = that.global_range_h; + rotation_range = that.rotation_range; + mode1 = that.mode1; + global = that.global; + rotate = that.rotate; + addtrackedframeoffset = that.addtrackedframeoffset; + mode2 = that.mode2; + draw_vectors = that.draw_vectors; + block_count = that.block_count; + block_x = that.block_x; + block_y = that.block_y; + global_positions = that.global_positions; + rotate_positions = that.rotate_positions; + global_block_w = that.global_block_w; + global_block_h = that.global_block_h; + rotation_block_w = that.rotation_block_w; + rotation_block_h = that.rotation_block_h; + magnitude = that.magnitude; + return_speed = that.return_speed; + mode3 = that.mode3; + track_frame = that.track_frame; + bottom_is_master = that.bottom_is_master; + horizontal_only = that.horizontal_only; + vertical_only = that.vertical_only; +} + +void MotionCVConfig::interpolate(MotionCVConfig &prev, + MotionCVConfig &next, + int64_t prev_frame, + int64_t next_frame, + int64_t current_frame) +{ + //double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); + //double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); + this->block_x = prev.block_x; + this->block_y = prev.block_y; + global_range_w = prev.global_range_w; + global_range_h = prev.global_range_h; + rotation_range = prev.rotation_range; + mode1 = prev.mode1; + global = prev.global; + rotate = prev.rotate; + addtrackedframeoffset = prev.addtrackedframeoffset; + mode2 = prev.mode2; + draw_vectors = prev.draw_vectors; + block_count = prev.block_count; + global_positions = prev.global_positions; + rotate_positions = prev.rotate_positions; + global_block_w = prev.global_block_w; + global_block_h = prev.global_block_h; + rotation_block_w = prev.rotation_block_w; + rotation_block_h = prev.rotation_block_h; + magnitude = prev.magnitude; + return_speed = prev.return_speed; + mode3 = prev.mode3; + track_frame = prev.track_frame; + bottom_is_master = prev.bottom_is_master; + horizontal_only = prev.horizontal_only; + vertical_only = prev.vertical_only; +} + + + + + + + + + + + + + + + + + + + +MotionCVMain::MotionCVMain(PluginServer *server) + : PluginVClient(server) +{ + engine = 0; + rotate_engine = 0; + motion_rotate = 0; + total_dx = 0; + total_dy = 0; + total_angle = 0; + overlayer = 0; + search_area = 0; + search_size = 0; + temp_frame = 0; + previous_frame_number = -1; + + prev_global_ref = 0; + current_global_ref = 0; + global_target_src = 0; + global_target_dst = 0; + + prev_rotate_ref = 0; + current_rotate_ref = 0; + rotate_target_src = 0; + rotate_target_dst = 0; +} + +MotionCVMain::~MotionCVMain() +{ + + delete engine; + delete overlayer; + delete [] search_area; + delete temp_frame; + delete rotate_engine; + delete motion_rotate; + + + delete prev_global_ref; + delete current_global_ref; + delete global_target_src; + delete global_target_dst; + + delete prev_rotate_ref; + delete current_rotate_ref; + delete rotate_target_src; + delete rotate_target_dst; +} + +const char* MotionCVMain::plugin_title() { return _("MotionCV"); } +int MotionCVMain::is_realtime() { return 1; } +int MotionCVMain::is_multichannel() { return 1; } + + +NEW_WINDOW_MACRO(MotionCVMain, MotionCVWindow) + +LOAD_CONFIGURATION_MACRO(MotionCVMain, MotionCVConfig) + + + +void MotionCVMain::update_gui() +{ + if(thread) + { + if(load_configuration()) + { + thread->window->lock_window("MotionCVMain::update_gui"); + MotionCVWindow *window = (MotionCVWindow *)thread->window; + + char string[BCTEXTLEN]; + sprintf(string, "%d", config.global_positions); + window->global_search_positions->set_text(string); + sprintf(string, "%d", config.rotate_positions); + window->rotation_search_positions->set_text(string); + + window->global_block_w->update(config.global_block_w); + window->global_block_h->update(config.global_block_h); + window->rotation_block_w->update(config.rotation_block_w); + window->rotation_block_h->update(config.rotation_block_h); + window->block_x->update(config.block_x); + window->block_y->update(config.block_y); + window->block_x_text->update((float)config.block_x); + window->block_y_text->update((float)config.block_y); + window->magnitude->update(config.magnitude); + window->return_speed->update(config.return_speed); + + + window->track_single->update(config.mode3 == MotionCVConfig::TRACK_SINGLE); + window->track_frame_number->update(config.track_frame); + window->track_previous->update(config.mode3 == MotionCVConfig::TRACK_PREVIOUS); + window->previous_same->update(config.mode3 == MotionCVConfig::PREVIOUS_SAME_BLOCK); + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + window->track_frame_number->disable(); + else + window->track_frame_number->enable(); + + window->mode1->set_text( + Mode1::to_text(config.mode1)); + window->mode2->set_text( + Mode2::to_text(config.mode2)); + window->mode3->set_text( + Mode3::to_text(config.horizontal_only, config.vertical_only)); + window->master_layer->set_text( + MasterLayer::to_text(config.bottom_is_master)); + + + window->update_mode(); + window->unlock_window(); + } + } +} + + + + +void MotionCVMain::save_data(KeyFrame *keyframe) +{ + FileXML output; + +// cause data to be stored directly in text + output.set_shared_output(keyframe->get_data(), MESSAGESIZE); + output.tag.set_title("MOTION"); + + output.tag.set_property("BLOCK_COUNT", config.block_count); + output.tag.set_property("GLOBAL_POSITIONS", config.global_positions); + output.tag.set_property("ROTATE_POSITIONS", config.rotate_positions); + output.tag.set_property("GLOBAL_BLOCK_W", config.global_block_w); + output.tag.set_property("GLOBAL_BLOCK_H", config.global_block_h); + output.tag.set_property("ROTATION_BLOCK_W", config.rotation_block_w); + output.tag.set_property("ROTATION_BLOCK_H", config.rotation_block_h); + output.tag.set_property("BLOCK_X", config.block_x); + output.tag.set_property("BLOCK_Y", config.block_y); + output.tag.set_property("GLOBAL_RANGE_W", config.global_range_w); + output.tag.set_property("GLOBAL_RANGE_H", config.global_range_h); + output.tag.set_property("ROTATION_RANGE", config.rotation_range); + output.tag.set_property("MAGNITUDE", config.magnitude); + output.tag.set_property("RETURN_SPEED", config.return_speed); + output.tag.set_property("MODE1", config.mode1); + output.tag.set_property("GLOBAL", config.global); + output.tag.set_property("ROTATE", config.rotate); + output.tag.set_property("ADDTRACKEDFRAMEOFFSET", config.addtrackedframeoffset); + output.tag.set_property("MODE2", config.mode2); + output.tag.set_property("DRAW_VECTORS", config.draw_vectors); + output.tag.set_property("MODE3", config.mode3); + output.tag.set_property("TRACK_FRAME", config.track_frame); + output.tag.set_property("BOTTOM_IS_MASTER", config.bottom_is_master); + output.tag.set_property("HORIZONTAL_ONLY", config.horizontal_only); + output.tag.set_property("VERTICAL_ONLY", config.vertical_only); + output.append_tag(); + output.tag.set_title("/MOTION"); + output.append_tag(); + output.terminate_string(); +} + +void MotionCVMain::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + + int result = 0; + + while(!result) + { + result = input.read_tag(); + + if(!result) + { + if(input.tag.title_is("MOTION")) + { + config.block_count = input.tag.get_property("BLOCK_COUNT", config.block_count); + config.global_positions = input.tag.get_property("GLOBAL_POSITIONS", config.global_positions); + config.rotate_positions = input.tag.get_property("ROTATE_POSITIONS", config.rotate_positions); + config.global_block_w = input.tag.get_property("GLOBAL_BLOCK_W", config.global_block_w); + config.global_block_h = input.tag.get_property("GLOBAL_BLOCK_H", config.global_block_h); + config.rotation_block_w = input.tag.get_property("ROTATION_BLOCK_W", config.rotation_block_w); + config.rotation_block_h = input.tag.get_property("ROTATION_BLOCK_H", config.rotation_block_h); + config.block_x = input.tag.get_property("BLOCK_X", config.block_x); + config.block_y = input.tag.get_property("BLOCK_Y", config.block_y); + config.global_range_w = input.tag.get_property("GLOBAL_RANGE_W", config.global_range_w); + config.global_range_h = input.tag.get_property("GLOBAL_RANGE_H", config.global_range_h); + config.rotation_range = input.tag.get_property("ROTATION_RANGE", config.rotation_range); + config.magnitude = input.tag.get_property("MAGNITUDE", config.magnitude); + config.return_speed = input.tag.get_property("RETURN_SPEED", config.return_speed); + config.mode1 = input.tag.get_property("MODE1", config.mode1); + config.global = input.tag.get_property("GLOBAL", config.global); + config.rotate = input.tag.get_property("ROTATE", config.rotate); + config.addtrackedframeoffset = input.tag.get_property("ADDTRACKEDFRAMEOFFSET", config.addtrackedframeoffset); + config.mode2 = input.tag.get_property("MODE2", config.mode2); + config.draw_vectors = input.tag.get_property("DRAW_VECTORS", config.draw_vectors); + config.mode3 = input.tag.get_property("MODE3", config.mode3); + config.track_frame = input.tag.get_property("TRACK_FRAME", config.track_frame); + config.bottom_is_master = input.tag.get_property("BOTTOM_IS_MASTER", config.bottom_is_master); + config.horizontal_only = input.tag.get_property("HORIZONTAL_ONLY", config.horizontal_only); + config.vertical_only = input.tag.get_property("VERTICAL_ONLY", config.vertical_only); + } + } + } + config.boundaries(); +} + + + + + + + + + +void MotionCVMain::allocate_temp(int w, int h, int color_model) +{ + if(temp_frame && + (temp_frame->get_w() != w || + temp_frame->get_h() != h)) + { + delete temp_frame; + temp_frame = 0; + } + if(!temp_frame) + temp_frame = new VFrame(w, h, color_model); +} + + + +void MotionCVMain::process_global() +{ + if(!engine) engine = new MotionCVScan(this, + PluginClient::get_project_smp() + 1, + PluginClient::get_project_smp() + 1); + +// Get the current motion vector between the previous and current frame + engine->scan_frame(current_global_ref, prev_global_ref); + current_dx = engine->dx_result; + current_dy = engine->dy_result; + +// Add current motion vector to accumulation vector. + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + { +// Retract over time + total_dx = (int64_t)total_dx * (100 - config.return_speed) / 100; + total_dy = (int64_t)total_dy * (100 - config.return_speed) / 100; + total_dx += engine->dx_result; + total_dy += engine->dy_result; + } + else +// Make accumulation vector current + { + total_dx = engine->dx_result; + total_dy = engine->dy_result; + } + +// Clamp accumulation vector + if(config.magnitude < 100) + { + //int block_w = (int64_t)config.global_block_w * + // current_global_ref->get_w() / 100; + //int block_h = (int64_t)config.global_block_h * + // current_global_ref->get_h() / 100; + int block_x_orig = (int64_t)(config.block_x * + current_global_ref->get_w() / + 100); + int block_y_orig = (int64_t)(config.block_y * + current_global_ref->get_h() / + 100); + + int max_block_x = (int64_t)(current_global_ref->get_w() - block_x_orig) * + OVERSAMPLE * + config.magnitude / + 100; + int max_block_y = (int64_t)(current_global_ref->get_h() - block_y_orig) * + OVERSAMPLE * + config.magnitude / + 100; + int min_block_x = (int64_t)-block_x_orig * + OVERSAMPLE * + config.magnitude / + 100; + int min_block_y = (int64_t)-block_y_orig * + OVERSAMPLE * + config.magnitude / + 100; + + CLAMP(total_dx, min_block_x, max_block_x); + CLAMP(total_dy, min_block_y, max_block_y); + } + +#ifdef DEBUG +printf("MotionCVMain::process_global 2 total_dx=%.02f total_dy=%.02f\n", +(float)total_dx / OVERSAMPLE, +(float)total_dy / OVERSAMPLE); +#endif + + if(config.mode3 != MotionCVConfig::TRACK_SINGLE && !config.rotate) + { +// Transfer current reference frame to previous reference frame and update +// counter. Must wait for rotate to compare. + prev_global_ref->copy_from(current_global_ref); + previous_frame_number = get_source_position(); + } + +// Decide what to do with target based on requested operation + int interpolation = NEAREST_NEIGHBOR; + float dx = 0; + float dy = 0; + switch(config.mode1) + { + case MotionCVConfig::NOTHING: + global_target_dst->copy_from(global_target_src); + break; + case MotionCVConfig::TRACK_PIXEL: + interpolation = NEAREST_NEIGHBOR; + dx = (int)(total_dx / OVERSAMPLE); + dy = (int)(total_dy / OVERSAMPLE); + break; + case MotionCVConfig::STABILIZE_PIXEL: + interpolation = NEAREST_NEIGHBOR; + dx = -(int)(total_dx / OVERSAMPLE); + dy = -(int)(total_dy / OVERSAMPLE); + break; + break; + case MotionCVConfig::TRACK: + interpolation = CUBIC_LINEAR; + dx = (float)total_dx / OVERSAMPLE; + dy = (float)total_dy / OVERSAMPLE; + break; + case MotionCVConfig::STABILIZE: + interpolation = CUBIC_LINEAR; + dx = -(float)total_dx / OVERSAMPLE; + dy = -(float)total_dy / OVERSAMPLE; + break; + } + + + if(config.mode1 != MotionCVConfig::NOTHING) + { + if(!overlayer) + overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); + global_target_dst->clear_frame(); + overlayer->overlay(global_target_dst, + global_target_src, + 0, + 0, + global_target_src->get_w(), + global_target_src->get_h(), + dx, + dy, + (float)global_target_src->get_w() + dx, + (float)global_target_src->get_h() + dy, + 1, + TRANSFER_REPLACE, + interpolation); + } +} + + + +void MotionCVMain::process_rotation() +{ + int block_x; + int block_y; + +// Convert the previous global reference into the previous rotation reference. +// Convert global target destination into rotation target source. + if(config.global) + { + if(!overlayer) + overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); + float dx; + float dy; + if(config.mode3 == MotionCVConfig::TRACK_SINGLE) + { + dx = (float)total_dx / OVERSAMPLE; + dy = (float)total_dy / OVERSAMPLE; + } + else + { + dx = (float)current_dx / OVERSAMPLE; + dy = (float)current_dy / OVERSAMPLE; + } + + prev_rotate_ref->clear_frame(); + overlayer->overlay(prev_rotate_ref, + prev_global_ref, + 0, + 0, + prev_global_ref->get_w(), + prev_global_ref->get_h(), + dx, + dy, + (float)prev_global_ref->get_w() + dx, + (float)prev_global_ref->get_h() + dy, + 1, + TRANSFER_REPLACE, + CUBIC_LINEAR); +// Pivot is destination global position + block_x = (int)(prev_rotate_ref->get_w() * + config.block_x / + 100 + + (float)total_dx / + OVERSAMPLE); + block_y = (int)(prev_rotate_ref->get_h() * + config.block_y / + 100 + + (float)total_dy / + OVERSAMPLE); +// Use the global target output as the rotation target input + rotate_target_src->copy_from(global_target_dst); +// Transfer current reference frame to previous reference frame for global. + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + { + prev_global_ref->copy_from(current_global_ref); + previous_frame_number = get_source_position(); + } + } + else + { +// Pivot is fixed + block_x = (int)(prev_rotate_ref->get_w() * + config.block_x / + 100); + block_y = (int)(prev_rotate_ref->get_h() * + config.block_y / + 100); + } + + + +// Get rotation + if(!motion_rotate) + motion_rotate = new RotateCVScan(this, + get_project_smp() + 1, + get_project_smp() + 1); + + current_angle = motion_rotate->scan_frame(prev_rotate_ref, + current_rotate_ref, + block_x, + block_y); + + + +// Add current rotation to accumulation + if(config.mode3 != MotionCVConfig::TRACK_SINGLE) + { +// Retract over time + total_angle = total_angle * (100 - config.return_speed) / 100; + total_angle += current_angle; + + if(!config.global) + { +// Transfer current reference frame to previous reference frame and update +// counter. + prev_rotate_ref->copy_from(current_rotate_ref); + previous_frame_number = get_source_position(); + } + } + else + { + total_angle = current_angle; + } + +#ifdef DEBUG +printf("MotionCVMain::process_rotation total_angle=%f\n", total_angle); +#endif + + +// Calculate rotation parameters based on requested operation + float angle = 0; + switch(config.mode1) + { + case MotionCVConfig::NOTHING: + rotate_target_dst->copy_from(rotate_target_src); + break; + case MotionCVConfig::TRACK: + case MotionCVConfig::TRACK_PIXEL: + angle = total_angle; + break; + case MotionCVConfig::STABILIZE: + case MotionCVConfig::STABILIZE_PIXEL: + angle = -total_angle; + break; + } + + + + if(config.mode1 != MotionCVConfig::NOTHING) + { + if(!rotate_engine) + rotate_engine = new AffineEngine(PluginClient::get_project_smp() + 1, + PluginClient::get_project_smp() + 1); + + rotate_target_dst->clear_frame(); + +// Determine pivot based on a number of factors. + switch(config.mode1) + { + case MotionCVConfig::TRACK: + case MotionCVConfig::TRACK_PIXEL: +// Use destination of global tracking. + rotate_engine->set_pivot(block_x, block_y); + break; + + case MotionCVConfig::STABILIZE: + case MotionCVConfig::STABILIZE_PIXEL: + if(config.global) + { +// Use origin of global stabilize operation + rotate_engine->set_pivot((int)(rotate_target_dst->get_w() * + config.block_x / + 100), + (int)(rotate_target_dst->get_h() * + config.block_y / + 100)); + + } + else + { +// Use origin + rotate_engine->set_pivot(block_x, block_y); + } + break; + } + + + rotate_engine->rotate(rotate_target_dst, rotate_target_src, angle); +// overlayer->overlay(rotate_target_dst, +// prev_rotate_ref, +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 1, +// TRANSFER_NORMAL, +// CUBIC_LINEAR); +// overlayer->overlay(rotate_target_dst, +// current_rotate_ref, +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 0, +// 0, +// prev_rotate_ref->get_w(), +// prev_rotate_ref->get_h(), +// 1, +// TRANSFER_NORMAL, +// CUBIC_LINEAR); + + + } + + +} + + + + + + + + + +int MotionCVMain::process_buffer(VFrame **frame, + int64_t start_position, + double frame_rate) +{ + int need_reconfigure = load_configuration(); + int color_model = frame[0]->get_color_model(); + w = frame[0]->get_w(); + h = frame[0]->get_h(); + + +#ifdef DEBUG +printf("MotionCVMain::process_buffer 1 start_position=%jd\n", start_position); +#endif + + +// Calculate the source and destination pointers for each of the operations. +// Get the layer to track motion in. + reference_layer = config.bottom_is_master ? + PluginClient::total_in_buffers - 1 : + 0; +// Get the layer to apply motion in. + target_layer = config.bottom_is_master ? + 0 : + PluginClient::total_in_buffers - 1; + + + output_frame = frame[target_layer]; + + +// Get the position of previous reference frame. + int64_t actual_previous_number; +// Skip if match frame not available + int skip_current = 0; + + + if(config.mode3 == MotionCVConfig::TRACK_SINGLE) + { + actual_previous_number = config.track_frame; + if(get_direction() == PLAY_REVERSE) + actual_previous_number++; + if(actual_previous_number == start_position) + skip_current = 1; + } + else + { + actual_previous_number = start_position; + if(get_direction() == PLAY_FORWARD) + { + actual_previous_number--; + if(actual_previous_number < get_source_start()) + skip_current = 1; + else + { + KeyFrame *keyframe = get_prev_keyframe(start_position, 1); + if(keyframe->position > 0 && + actual_previous_number < keyframe->position) + skip_current = 1; + } + } + else + { + actual_previous_number++; + if(actual_previous_number >= get_source_start() + get_total_len()) + skip_current = 1; + else + { + KeyFrame *keyframe = get_next_keyframe(start_position, 1); + if(keyframe->position > 0 && + actual_previous_number >= keyframe->position) + skip_current = 1; + } + } + +// Only count motion since last keyframe + + + } + + + if(!config.global && !config.rotate) skip_current = 1; + + + + +// printf("process_realtime %d %lld %lld\n", +// skip_current, +// previous_frame_number, +// actual_previous_number); +// Load match frame and reset vectors + int need_reload = !skip_current && + (previous_frame_number != actual_previous_number || + need_reconfigure); + if(need_reload) + { + total_dx = 0; + total_dy = 0; + total_angle = 0; + previous_frame_number = actual_previous_number; + } + + + if(skip_current) + { + total_dx = 0; + total_dy = 0; + current_dx = 0; + current_dy = 0; + total_angle = 0; + current_angle = 0; + } + + + + +// Get the global pointers. Here we walk through the sequence of events. + if(config.global) + { +// Assume global only. Global reads previous frame and compares +// with current frame to get the current translation. +// The center of the search area is fixed in compensate mode or +// the user value + the accumulation vector in track mode. + if(!prev_global_ref) + prev_global_ref = new VFrame(w, h, color_model); + if(!current_global_ref) + current_global_ref = new VFrame(w, h, color_model); + +// Global loads the current target frame into the src and +// writes it to the dst frame with desired translation. + if(!global_target_src) + global_target_src = new VFrame(w, h, color_model); + if(!global_target_dst) + global_target_dst = new VFrame(w, h, color_model); + + +// Load the global frames + if(need_reload) + { + read_frame(prev_global_ref, + reference_layer, + previous_frame_number, + frame_rate, + 0); + } + + read_frame(current_global_ref, + reference_layer, + start_position, + frame_rate, + 0); + read_frame(global_target_src, + target_layer, + start_position, + frame_rate, + 0); + + + +// Global followed by rotate + if(config.rotate) + { +// Must translate the previous global reference by the current global +// accumulation vector to match the current global reference. +// The center of the search area is always the user value + the accumulation +// vector. + if(!prev_rotate_ref) + prev_rotate_ref = new VFrame(w, h, color_model); +// The current global reference is the current rotation reference. + if(!current_rotate_ref) + current_rotate_ref = new VFrame(w, h, color_model); + current_rotate_ref->copy_from(current_global_ref); + +// The global target destination is copied to the rotation target source +// then written to the rotation output with rotation. +// The pivot for the rotation is the center of the search area +// if we're tracking. +// The pivot is fixed to the user position if we're compensating. + if(!rotate_target_src) + rotate_target_src = new VFrame(w, h, color_model); + if(!rotate_target_dst) + rotate_target_dst = new VFrame(w,h , color_model); + } + } + else +// Rotation only + if(config.rotate) + { +// Rotation reads the previous reference frame and compares it with current +// reference frame. + if(!prev_rotate_ref) + prev_rotate_ref = new VFrame(w, h, color_model); + if(!current_rotate_ref) + current_rotate_ref = new VFrame(w, h, color_model); + +// Rotation loads target frame to temporary, rotates it, and writes it to the +// target frame. The pivot is always fixed. + if(!rotate_target_src) + rotate_target_src = new VFrame(w, h, color_model); + if(!rotate_target_dst) + rotate_target_dst = new VFrame(w,h , color_model); + + +// Load the rotate frames + if(need_reload) + { + read_frame(prev_rotate_ref, + reference_layer, + previous_frame_number, + frame_rate, + 0); + } + read_frame(current_rotate_ref, + reference_layer, + start_position, + frame_rate, + 0); + read_frame(rotate_target_src, + target_layer, + start_position, + frame_rate, + 0); + } + + + + + + + + + + + if(!skip_current) + { +// Get position change from previous frame to current frame + if(config.global) process_global(); +// Get rotation change from previous frame to current frame + if(config.rotate) process_rotation(); +//frame[target_layer]->copy_from(prev_rotate_ref); +//frame[target_layer]->copy_from(current_rotate_ref); + } + + + + + + +// Transfer the relevant target frame to the output + if(!skip_current) + { + if(config.rotate) + { + frame[target_layer]->copy_from(rotate_target_dst); + } + else + { + frame[target_layer]->copy_from(global_target_dst); + } + } + else +// Read the target destination directly + { + read_frame(frame[target_layer], + target_layer, + start_position, + frame_rate, + 0); + } + + if(config.draw_vectors) + { + draw_vectors(frame[target_layer]); + } + +#ifdef DEBUG +printf("MotionCVMain::process_buffer 100\n"); +#endif + return 0; +} + + +void MotionCVMain::clamp_scan(int w, + int h, + int *block_x1, + int *block_y1, + int *block_x2, + int *block_y2, + int *scan_x1, + int *scan_y1, + int *scan_x2, + int *scan_y2, + int use_absolute) +{ +// printf("MotionCVMain::clamp_scan 1 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", +// w, +// h, +// *block_x1, +// *block_y1, +// *block_x2, +// *block_y2, +// *scan_x1, +// *scan_y1, +// *scan_x2, +// *scan_y2, +// use_absolute); + + if(use_absolute) + { +// scan is always out of range before block. + if(*scan_x1 < 0) + { + int difference = -*scan_x1; + *block_x1 += difference; + *scan_x1 = 0; + } + + if(*scan_y1 < 0) + { + int difference = -*scan_y1; + *block_y1 += difference; + *scan_y1 = 0; + } + + if(*scan_x2 > w) + { + int difference = *scan_x2 - w; + *block_x2 -= difference; + *scan_x2 -= difference; + } + + if(*scan_y2 > h) + { + int difference = *scan_y2 - h; + *block_y2 -= difference; + *scan_y2 -= difference; + } + + CLAMP(*scan_x1, 0, w); + CLAMP(*scan_y1, 0, h); + CLAMP(*scan_x2, 0, w); + CLAMP(*scan_y2, 0, h); + } + else + { + if(*scan_x1 < 0) + { + int difference = -*scan_x1; + *block_x1 += difference; + *scan_x2 += difference; + *scan_x1 = 0; + } + + if(*scan_y1 < 0) + { + int difference = -*scan_y1; + *block_y1 += difference; + *scan_y2 += difference; + *scan_y1 = 0; + } + + if(*scan_x2 - *block_x1 + *block_x2 > w) + { + int difference = *scan_x2 - *block_x1 + *block_x2 - w; + *block_x2 -= difference; + } + + if(*scan_y2 - *block_y1 + *block_y2 > h) + { + int difference = *scan_y2 - *block_y1 + *block_y2 - h; + *block_y2 -= difference; + } + +// CLAMP(*scan_x1, 0, w - (*block_x2 - *block_x1)); +// CLAMP(*scan_y1, 0, h - (*block_y2 - *block_y1)); +// CLAMP(*scan_x2, 0, w - (*block_x2 - *block_x1)); +// CLAMP(*scan_y2, 0, h - (*block_y2 - *block_y1)); + } + +// Sanity checks which break the calculation but should never happen if the +// center of the block is inside the frame. + CLAMP(*block_x1, 0, w); + CLAMP(*block_x2, 0, w); + CLAMP(*block_y1, 0, h); + CLAMP(*block_y2, 0, h); + +// printf("MotionCVMain::clamp_scan 2 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", +// w, +// h, +// *block_x1, +// *block_y1, +// *block_x2, +// *block_y2, +// *scan_x1, +// *scan_y1, +// *scan_x2, +// *scan_y2, +// use_absolute); +} + + + +void MotionCVMain::draw_vectors(VFrame *frame) +{ + int w = frame->get_w(); + int h = frame->get_h(); + int global_x1, global_y1; + int global_x2, global_y2; + int block_x, block_y; + int block_w, block_h; + int block_x1, block_y1; + int block_x2, block_y2; + int block_x3, block_y3; + int block_x4, block_y4; + int search_w, search_h; + int search_x1, search_y1; + int search_x2, search_y2; + //int search_x3, search_y3; + //int search_x4, search_y4; + + if(config.global) + { +// Get vector +// Start of vector is center of previous block. +// End of vector is total accumulation. + if(config.mode3 == MotionCVConfig::TRACK_SINGLE) + { + global_x1 = (int64_t)(config.block_x * + w / + 100); + global_y1 = (int64_t)(config.block_y * + h / + 100); + global_x2 = global_x1 + total_dx / OVERSAMPLE; + global_y2 = global_y1 + total_dy / OVERSAMPLE; +//printf("MotionCVMain::draw_vectors %d %d %d %d %d %d\n", total_dx, total_dy, global_x1, global_y1, global_x2, global_y2); + } + else +// Start of vector is center of previous block. +// End of vector is current change. + if(config.mode3 == MotionCVConfig::PREVIOUS_SAME_BLOCK) + { + global_x1 = (int64_t)(config.block_x * + w / + 100); + global_y1 = (int64_t)(config.block_y * + h / + 100); + global_x2 = global_x1 + current_dx / OVERSAMPLE; + global_y2 = global_y1 + current_dy / OVERSAMPLE; + } + else + { + global_x1 = (int64_t)(config.block_x * + w / + 100 + + (total_dx - current_dx) / + OVERSAMPLE); + global_y1 = (int64_t)(config.block_y * + h / + 100 + + (total_dy - current_dy) / + OVERSAMPLE); + global_x2 = (int64_t)(config.block_x * + w / + 100 + + total_dx / + OVERSAMPLE); + global_y2 = (int64_t)(config.block_y * + h / + 100 + + total_dy / + OVERSAMPLE); + } + + block_x = global_x1; + block_y = global_y1; + block_w = config.global_block_w * w / 100; + block_h = config.global_block_h * h / 100; + block_x1 = block_x - block_w / 2; + block_y1 = block_y - block_h / 2; + block_x2 = block_x + block_w / 2; + block_y2 = block_y + block_h / 2; + search_w = config.global_range_w * w / 100; + search_h = config.global_range_h * h / 100; + search_x1 = block_x1 - search_w / 2; + search_y1 = block_y1 - search_h / 2; + search_x2 = block_x2 + search_w / 2; + search_y2 = block_y2 + search_h / 2; + +// printf("MotionCVMain::draw_vectors %d %d %d %d %d %d %d %d %d %d %d %d\n", +// global_x1, +// global_y1, +// block_w, +// block_h, +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// search_x1, +// search_y1, +// search_x2, +// search_y2); + + clamp_scan(w, + h, + &block_x1, + &block_y1, + &block_x2, + &block_y2, + &search_x1, + &search_y1, + &search_x2, + &search_y2, + 1); + +// Vector + draw_arrow(frame, global_x1, global_y1, global_x2, global_y2); + +// Macroblock + draw_line(frame, block_x1, block_y1, block_x2, block_y1); + draw_line(frame, block_x2, block_y1, block_x2, block_y2); + draw_line(frame, block_x2, block_y2, block_x1, block_y2); + draw_line(frame, block_x1, block_y2, block_x1, block_y1); + + +// Search area + draw_line(frame, search_x1, search_y1, search_x2, search_y1); + draw_line(frame, search_x2, search_y1, search_x2, search_y2); + draw_line(frame, search_x2, search_y2, search_x1, search_y2); + draw_line(frame, search_x1, search_y2, search_x1, search_y1); + +// Block should be endpoint of motion + if(config.rotate) + { + block_x = global_x2; + block_y = global_y2; + } + } + else + { + block_x = (int64_t)(config.block_x * w / 100); + block_y = (int64_t)(config.block_y * h / 100); + } + + block_w = config.rotation_block_w * w / 100; + block_h = config.rotation_block_h * h / 100; + if(config.rotate) + { + float angle = total_angle * 2 * M_PI / 360; + double base_angle1 = atan((float)block_h / block_w); + double base_angle2 = atan((float)block_w / block_h); + double target_angle1 = base_angle1 + angle; + double target_angle2 = base_angle2 + angle; + double radius = sqrt(block_w * block_w + block_h * block_h) / 2; + block_x1 = (int)(block_x - cos(target_angle1) * radius); + block_y1 = (int)(block_y - sin(target_angle1) * radius); + block_x2 = (int)(block_x + sin(target_angle2) * radius); + block_y2 = (int)(block_y - cos(target_angle2) * radius); + block_x3 = (int)(block_x - sin(target_angle2) * radius); + block_y3 = (int)(block_y + cos(target_angle2) * radius); + block_x4 = (int)(block_x + cos(target_angle1) * radius); + block_y4 = (int)(block_y + sin(target_angle1) * radius); + + draw_line(frame, block_x1, block_y1, block_x2, block_y2); + draw_line(frame, block_x2, block_y2, block_x4, block_y4); + draw_line(frame, block_x4, block_y4, block_x3, block_y3); + draw_line(frame, block_x3, block_y3, block_x1, block_y1); + + +// Center + if(!config.global) + { + draw_line(frame, block_x, block_y - 5, block_x, block_y + 6); + draw_line(frame, block_x - 5, block_y, block_x + 6, block_y); + } + } +} + + + +void MotionCVMain::draw_pixel(VFrame *frame, int x, int y) +{ + if(!(x >= 0 && y >= 0 && x < frame->get_w() && y < frame->get_h())) return; + +#define DRAW_PIXEL(x, y, components, do_yuv, max, type) \ +{ \ + type **rows = (type**)frame->get_rows(); \ + rows[y][x * components] = max - rows[y][x * components]; \ + if(!do_yuv) \ + { \ + rows[y][x * components + 1] = max - rows[y][x * components + 1]; \ + rows[y][x * components + 2] = max - rows[y][x * components + 2]; \ + } \ + else \ + { \ + rows[y][x * components + 1] = (max / 2 + 1) - rows[y][x * components + 1]; \ + rows[y][x * components + 2] = (max / 2 + 1) - rows[y][x * components + 2]; \ + } \ + if(components == 4) \ + rows[y][x * components + 3] = max; \ +} + + + switch(frame->get_color_model()) + { + case BC_RGB888: + DRAW_PIXEL(x, y, 3, 0, 0xff, unsigned char); + break; + case BC_RGBA8888: + DRAW_PIXEL(x, y, 4, 0, 0xff, unsigned char); + break; + case BC_RGB_FLOAT: + DRAW_PIXEL(x, y, 3, 0, 1.0, float); + break; + case BC_RGBA_FLOAT: + DRAW_PIXEL(x, y, 4, 0, 1.0, float); + break; + case BC_YUV888: + DRAW_PIXEL(x, y, 3, 1, 0xff, unsigned char); + break; + case BC_YUVA8888: + DRAW_PIXEL(x, y, 4, 1, 0xff, unsigned char); + break; + case BC_RGB161616: + DRAW_PIXEL(x, y, 3, 0, 0xffff, uint16_t); + break; + case BC_YUV161616: + DRAW_PIXEL(x, y, 3, 1, 0xffff, uint16_t); + break; + case BC_RGBA16161616: + DRAW_PIXEL(x, y, 4, 0, 0xffff, uint16_t); + break; + case BC_YUVA16161616: + DRAW_PIXEL(x, y, 4, 1, 0xffff, uint16_t); + break; + } +} + + +void MotionCVMain::draw_line(VFrame *frame, int x1, int y1, int x2, int y2) +{ + int w = labs(x2 - x1); + int h = labs(y2 - y1); +//printf("MotionCVMain::draw_line 1 %d %d %d %d\n", x1, y1, x2, y2); + + if(!w && !h) + { + draw_pixel(frame, x1, y1); + } + else + if(w > h) + { +// Flip coordinates so x1 < x2 + if(x2 < x1) + { + y2 ^= y1; + y1 ^= y2; + y2 ^= y1; + x1 ^= x2; + x2 ^= x1; + x1 ^= x2; + } + int numerator = y2 - y1; + int denominator = x2 - x1; + for(int i = x1; i < x2; i++) + { + int y = y1 + (int64_t)(i - x1) * (int64_t)numerator / (int64_t)denominator; + draw_pixel(frame, i, y); + } + } + else + { +// Flip coordinates so y1 < y2 + if(y2 < y1) + { + y2 ^= y1; + y1 ^= y2; + y2 ^= y1; + x1 ^= x2; + x2 ^= x1; + x1 ^= x2; + } + int numerator = x2 - x1; + int denominator = y2 - y1; + for(int i = y1; i < y2; i++) + { + int x = x1 + (int64_t)(i - y1) * (int64_t)numerator / (int64_t)denominator; + draw_pixel(frame, x, i); + } + } +//printf("MotionCVMain::draw_line 2\n"); +} + +#define ARROW_SIZE 10 +void MotionCVMain::draw_arrow(VFrame *frame, int x1, int y1, int x2, int y2) +{ + double angle = atan((float)(y2 - y1) / (float)(x2 - x1)); + double angle1 = angle + (float)145 / 360 * 2 * 3.14159265; + double angle2 = angle - (float)145 / 360 * 2 * 3.14159265; + int x3; + int y3; + int x4; + int y4; + if(x2 < x1) + { + x3 = x2 - (int)(ARROW_SIZE * cos(angle1)); + y3 = y2 - (int)(ARROW_SIZE * sin(angle1)); + x4 = x2 - (int)(ARROW_SIZE * cos(angle2)); + y4 = y2 - (int)(ARROW_SIZE * sin(angle2)); + } + else + { + x3 = x2 + (int)(ARROW_SIZE * cos(angle1)); + y3 = y2 + (int)(ARROW_SIZE * sin(angle1)); + x4 = x2 + (int)(ARROW_SIZE * cos(angle2)); + y4 = y2 + (int)(ARROW_SIZE * sin(angle2)); + } + +// Main vector + draw_line(frame, x1, y1, x2, y2); +// draw_line(frame, x1, y1 + 1, x2, y2 + 1); + +// Arrow line + if(abs(y2 - y1) || abs(x2 - x1)) draw_line(frame, x2, y2, x3, y3); +// draw_line(frame, x2, y2 + 1, x3, y3 + 1); +// Arrow line + if(abs(y2 - y1) || abs(x2 - x1)) draw_line(frame, x2, y2, x4, y4); +// draw_line(frame, x2, y2 + 1, x4, y4 + 1); +} + + + + +#define ABS_DIFF(type, temp_type, multiplier, components) \ +{ \ + temp_type result_temp = 0; \ + for(int i = 0; i < h; i++) \ + { \ + type *prev_row = (type*)prev_ptr; \ + type *current_row = (type*)current_ptr; \ + for(int j = 0; j < w; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + temp_type difference; \ + difference = *prev_row++ - *current_row++; \ + if(difference < 0) \ + result_temp -= difference; \ + else \ + result_temp += difference; \ + } \ + if(components == 4) \ + { \ + prev_row++; \ + current_row++; \ + } \ + } \ + prev_ptr += row_bytes; \ + current_ptr += row_bytes; \ + } \ + result = (int64_t)(result_temp * multiplier); \ +} + +int64_t MotionCVMain::abs_diff(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model) +{ + int64_t result = 0; + switch(color_model) + { + case BC_RGB888: + ABS_DIFF(unsigned char, int64_t, 1, 3) + break; + case BC_RGBA8888: + ABS_DIFF(unsigned char, int64_t, 1, 4) + break; + case BC_RGB_FLOAT: + ABS_DIFF(float, double, 0x10000, 3) + break; + case BC_RGBA_FLOAT: + ABS_DIFF(float, double, 0x10000, 4) + break; + case BC_YUV888: + ABS_DIFF(unsigned char, int64_t, 1, 3) + break; + case BC_YUVA8888: + ABS_DIFF(unsigned char, int64_t, 1, 4) + break; + case BC_YUV161616: + ABS_DIFF(uint16_t, int64_t, 1, 3) + break; + case BC_YUVA16161616: + ABS_DIFF(uint16_t, int64_t, 1, 4) + break; + } + return result; +} + + + +#define ABS_DIFF_SUB(type, temp_type, multiplier, components) \ +{ \ + temp_type result_temp = 0; \ + temp_type y2_fraction = sub_y * 0x100 / OVERSAMPLE; \ + temp_type y1_fraction = 0x100 - y2_fraction; \ + temp_type x2_fraction = sub_x * 0x100 / OVERSAMPLE; \ + temp_type x1_fraction = 0x100 - x2_fraction; \ + for(int i = 0; i < h_sub; i++) \ + { \ + type *prev_row1 = (type*)prev_ptr; \ + type *prev_row2 = (type*)prev_ptr + components; \ + type *prev_row3 = (type*)(prev_ptr + row_bytes); \ + type *prev_row4 = (type*)(prev_ptr + row_bytes) + components; \ + type *current_row = (type*)current_ptr; \ + for(int j = 0; j < w_sub; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + temp_type difference; \ + temp_type prev_value = \ + (*prev_row1++ * x1_fraction * y1_fraction + \ + *prev_row2++ * x2_fraction * y1_fraction + \ + *prev_row3++ * x1_fraction * y2_fraction + \ + *prev_row4++ * x2_fraction * y2_fraction) / \ + 0x100 / 0x100; \ + temp_type current_value = *current_row++; \ + difference = prev_value - current_value; \ + if(difference < 0) \ + result_temp -= difference; \ + else \ + result_temp += difference; \ + } \ + \ + if(components == 4) \ + { \ + prev_row1++; \ + prev_row2++; \ + prev_row3++; \ + prev_row4++; \ + current_row++; \ + } \ + } \ + prev_ptr += row_bytes; \ + current_ptr += row_bytes; \ + } \ + result = (int64_t)(result_temp * multiplier); \ +} + + + + +int64_t MotionCVMain::abs_diff_sub(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model, + int sub_x, + int sub_y) +{ + int h_sub = h - 1; + int w_sub = w - 1; + int64_t result = 0; + + switch(color_model) + { + case BC_RGB888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) + break; + case BC_RGBA8888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) + break; + case BC_RGB_FLOAT: + ABS_DIFF_SUB(float, double, 0x10000, 3) + break; + case BC_RGBA_FLOAT: + ABS_DIFF_SUB(float, double, 0x10000, 4) + break; + case BC_YUV888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) + break; + case BC_YUVA8888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) + break; + case BC_YUV161616: + ABS_DIFF_SUB(uint16_t, int64_t, 1, 3) + break; + case BC_YUVA16161616: + ABS_DIFF_SUB(uint16_t, int64_t, 1, 4) + break; + } + return result; +} + + + + + +MotionCVScanPackage::MotionCVScanPackage() + : LoadPackage() +{ + valid = 1; +} + + + + + + +MotionCVScanUnit::MotionCVScanUnit(MotionCVScan *server, + MotionCVMain *plugin) + : LoadClient(server) +{ + this->plugin = plugin; + this->server = server; + cache_lock = new Mutex("MotionCVScanUnit::cache_lock"); +} + +MotionCVScanUnit::~MotionCVScanUnit() +{ + delete cache_lock; +} + + + +void MotionCVScanUnit::process_package(LoadPackage *package) +{ + MotionCVScanPackage *pkg = (MotionCVScanPackage*)package; + //int w = server->current_frame->get_w(); + //int h = server->current_frame->get_h(); + int color_model = server->current_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = server->current_frame->get_bytes_per_line(); + + + + + + + + + + + + +// Single pixel + if(!server->subpixel) + { + int search_x = pkg->scan_x1 + (pkg->pixel % (pkg->scan_x2 - pkg->scan_x1)); + int search_y = pkg->scan_y1 + (pkg->pixel / (pkg->scan_x2 - pkg->scan_x1)); + +// Try cache + pkg->difference1 = server->get_cache(search_x, search_y); + if(pkg->difference1 < 0) + { +//printf("MotionCVScanUnit::process_package 1 %d %d\n", +//search_x, search_y, pkg->block_x2 - pkg->block_x1, pkg->block_y2 - pkg->block_y1); +// Pointers to first pixel in each block + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + search_y] + + search_x * pixel_size; + unsigned char *current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; +// Scan block + pkg->difference1 = plugin->abs_diff(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model); +//printf("MotionCVScanUnit::process_package 2\n"); + server->put_cache(search_x, search_y, pkg->difference1); + } + } + + + + + + + + else + + + + + + + + +// Sub pixel + { + int sub_x = pkg->pixel % (OVERSAMPLE * 2 - 1) + 1; + int sub_y = pkg->pixel / (OVERSAMPLE * 2 - 1) + 1; + + if(plugin->config.horizontal_only) + { + sub_y = 0; + } + + if(plugin->config.vertical_only) + { + sub_x = 0; + } + + int search_x = pkg->scan_x1 + sub_x / OVERSAMPLE; + int search_y = pkg->scan_y1 + sub_y / OVERSAMPLE; + sub_x %= OVERSAMPLE; + sub_y %= OVERSAMPLE; + + + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + search_y] + + search_x * pixel_size; + unsigned char *current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; + +// With subpixel, there are two ways to compare each position, one by shifting +// the previous frame and two by shifting the current frame. + pkg->difference1 = plugin->abs_diff_sub(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + sub_x, + sub_y); + pkg->difference2 = plugin->abs_diff_sub(current_ptr, + prev_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + sub_x, + sub_y); +// printf("MotionCVScanUnit::process_package sub_x=%d sub_y=%d search_x=%d search_y=%d diff1=%lld diff2=%lld\n", +// sub_x, +// sub_y, +// search_x, +// search_y, +// pkg->difference1, +// pkg->difference2); + } + + + + +} + + + + + + + + + + +int64_t MotionCVScanUnit::get_cache(int x, int y) +{ + int64_t result = -1; + cache_lock->lock("MotionCVScanUnit::get_cache"); + for(int i = 0; i < cache.total; i++) + { + MotionCVScanCache *ptr = cache.values[i]; + if(ptr->x == x && ptr->y == y) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void MotionCVScanUnit::put_cache(int x, int y, int64_t difference) +{ + MotionCVScanCache *ptr = new MotionCVScanCache(x, y, difference); + cache_lock->lock("MotionCVScanUnit::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + + + + + + + + + +MotionCVScan::MotionCVScan(MotionCVMain *plugin, + int total_clients, + int total_packages) + : LoadServer( +//1, 1 +total_clients, total_packages +) +{ + this->plugin = plugin; + cache_lock = new Mutex("MotionCVScan::cache_lock"); +} + +MotionCVScan::~MotionCVScan() +{ + delete cache_lock; +} + + +void MotionCVScan::init_packages() +{ +// Set package coords + for(int i = 0; i < get_total_packages(); i++) + { + MotionCVScanPackage *pkg = (MotionCVScanPackage*)get_package(i); + + pkg->block_x1 = block_x1; + pkg->block_x2 = block_x2; + pkg->block_y1 = block_y1; + pkg->block_y2 = block_y2; + pkg->scan_x1 = scan_x1; + pkg->scan_x2 = scan_x2; + pkg->scan_y1 = scan_y1; + pkg->scan_y2 = scan_y2; + pkg->pixel = (int64_t)i * (int64_t)total_pixels / (int64_t)total_steps; + pkg->difference1 = 0; + pkg->difference2 = 0; + pkg->dx = 0; + pkg->dy = 0; + pkg->valid = 1; + } +} + +LoadClient* MotionCVScan::new_client() +{ + return new MotionCVScanUnit(this, plugin); +} + +LoadPackage* MotionCVScan::new_package() +{ + return new MotionCVScanPackage; +} + + +void MotionCVScan::scan_frame(VFrame *previous_frame, + VFrame *current_frame) +{ + this->previous_frame = previous_frame; + this->current_frame = current_frame; + subpixel = 0; + + cache.remove_all_objects(); + + +// Single macroblock + int w = current_frame->get_w(); + int h = current_frame->get_h(); + +// Initial search parameters + int scan_w = w * plugin->config.global_range_w / 100; + int scan_h = h * plugin->config.global_range_h / 100; + int block_w = w * plugin->config.global_block_w / 100; + int block_h = h * plugin->config.global_block_h / 100; + +// Location of block in previous frame + block_x1 = (int)(w * plugin->config.block_x / 100 - block_w / 2); + block_y1 = (int)(h * plugin->config.block_y / 100 - block_h / 2); + block_x2 = (int)(w * plugin->config.block_x / 100 + block_w / 2); + block_y2 = (int)(h * plugin->config.block_y / 100 + block_h / 2); + +// Offset to location of previous block. This offset needn't be very accurate +// since it's the offset of the previous image and current image we want. + if(plugin->config.mode3 == MotionCVConfig::TRACK_PREVIOUS) + { + block_x1 += plugin->total_dx / OVERSAMPLE; + block_y1 += plugin->total_dy / OVERSAMPLE; + block_x2 += plugin->total_dx / OVERSAMPLE; + block_y2 += plugin->total_dy / OVERSAMPLE; + } + + skip = 0; + + switch(plugin->config.mode2) + { +// Don't calculate + case MotionCVConfig::NO_CALCULATE: + dx_result = 0; + dy_result = 0; + skip = 1; + break; + + case MotionCVConfig::LOAD: + { +// Load result from disk + char string[BCTEXTLEN]; + sprintf(string, "%s%06jd", MOTION_FILE, plugin->get_source_position()); + FILE *input = fopen(string, "r"); + if(input) + { + fscanf(input, + "%d %d", + &dx_result, + &dy_result); + fclose(input); + skip = 1; + } + break; + } + +// Scan from scratch + default: + skip = 0; + break; + } + +// Perform scan + if(!skip) + { +// Location of block in current frame + int x_result = block_x1; + int y_result = block_y1; + +// printf("MotionCVScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", +// block_x1 + block_w / 2, +// block_y1 + block_h / 2, +// block_w, +// block_h, +// block_x1, +// block_y1, +// block_x2, +// block_y2); + + while(1) + { + scan_x1 = x_result - scan_w / 2; + scan_y1 = y_result - scan_h / 2; + scan_x2 = x_result + scan_w / 2; + scan_y2 = y_result + scan_h / 2; + + + +// Zero out requested values + if(plugin->config.horizontal_only) + { + scan_y1 = block_y1; + scan_y2 = block_y1 + 1; + } + if(plugin->config.vertical_only) + { + scan_x1 = block_x1; + scan_x2 = block_x1 + 1; + } + +// printf("MotionCVScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2); +// Clamp the block coords before the scan so we get useful scan coords. + MotionCVMain::clamp_scan(w, + h, + &block_x1, + &block_y1, + &block_x2, + &block_y2, + &scan_x1, + &scan_y1, + &scan_x2, + &scan_y2, + 0); +// printf("MotionCVScan::scan_frame 1\n block_x1=%d block_y1=%d block_x2=%d block_y2=%d\n scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d\n x_result=%d y_result=%d\n", +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2, +// x_result, +// y_result); + + +// Give up if invalid coords. + if(scan_y2 <= scan_y1 || + scan_x2 <= scan_x1 || + block_x2 <= block_x1 || + block_y2 <= block_y1) + break; + +// For subpixel, the top row and left column are skipped + if(subpixel) + { + if(plugin->config.horizontal_only || + plugin->config.vertical_only) + { + total_pixels = 4 * OVERSAMPLE * OVERSAMPLE - 4 * OVERSAMPLE; + } + else + { + total_pixels = 4 * OVERSAMPLE; + } + + total_steps = total_pixels; + + set_package_count(total_steps); + process_packages(); + +// Get least difference + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + MotionCVScanPackage *pkg = (MotionCVScanPackage*)get_package(i); + if(pkg->difference1 < min_difference || min_difference == -1) + { + min_difference = pkg->difference1; + + if(plugin->config.vertical_only) + x_result = scan_x1 * OVERSAMPLE; + else + x_result = scan_x1 * OVERSAMPLE + + (pkg->pixel % (OVERSAMPLE * 2 - 1)) + 1; + + if(plugin->config.horizontal_only) + y_result = scan_y1 * OVERSAMPLE; + else + y_result = scan_y1 * OVERSAMPLE + + (pkg->pixel / (OVERSAMPLE * 2 - 1)) + 1; + + +// Fill in results + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; + } + + if(pkg->difference2 < min_difference) + { + min_difference = pkg->difference2; + + if(plugin->config.vertical_only) + x_result = scan_x1 * OVERSAMPLE; + else + x_result = scan_x2 * OVERSAMPLE - + ((pkg->pixel % (OVERSAMPLE * 2 - 1)) + 1); + + if(plugin->config.horizontal_only) + y_result = scan_y1 * OVERSAMPLE; + else + y_result = scan_y2 * OVERSAMPLE - + ((pkg->pixel / (OVERSAMPLE * 2 - 1)) + 1); + + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; + } + } + +//printf("MotionCVScan::scan_frame 1 %d %d %d %d\n", block_x1, block_y1, x_result, y_result); + break; + } + else + { + total_pixels = (scan_x2 - scan_x1) * (scan_y2 - scan_y1); + total_steps = MIN(plugin->config.global_positions, total_pixels); + + set_package_count(total_steps); + process_packages(); + +// Get least difference + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + MotionCVScanPackage *pkg = (MotionCVScanPackage*)get_package(i); + if(pkg->difference1 < min_difference || min_difference == -1) + { + min_difference = pkg->difference1; + x_result = scan_x1 + (pkg->pixel % (scan_x2 - scan_x1)); + y_result = scan_y1 + (pkg->pixel / (scan_x2 - scan_x1)); + x_result *= OVERSAMPLE; + y_result *= OVERSAMPLE; + } + } + +// printf("MotionCVScan::scan_frame 10 total_steps=%d total_pixels=%d subpixel=%d\n", +// total_steps, +// total_pixels, +// subpixel); +// +// printf(" scan w=%d h=%d scan x1=%d y1=%d x2=%d y2=%d\n", +// scan_w, +// scan_h, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2); +// +// printf("MotionCVScan::scan_frame 2 block x1=%d y1=%d x2=%d y2=%d result x=%.2f y=%.2f\n", +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// (float)x_result / 4, +// (float)y_result / 4); + + +// If a new search is required, rescale results back to pixels. + if(total_steps >= total_pixels) + { +// Single pixel accuracy reached. Now do exhaustive subpixel search. + if(plugin->config.mode1 == MotionCVConfig::STABILIZE || + plugin->config.mode1 == MotionCVConfig::TRACK || + plugin->config.mode1 == MotionCVConfig::NOTHING) + { + x_result /= OVERSAMPLE; + y_result /= OVERSAMPLE; + scan_w = 2; + scan_h = 2; + subpixel = 1; + } + else + { +// Fill in results and quit + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; + break; + } + } + else +// Reduce scan area and try again + { + scan_w = (scan_x2 - scan_x1) / 2; + scan_h = (scan_y2 - scan_y1) / 2; + x_result /= OVERSAMPLE; + y_result /= OVERSAMPLE; + } + } + } + + dx_result *= -1; + dy_result *= -1; + + // Add offsets from the "tracked single frame" + if (plugin->config.addtrackedframeoffset) { + int tf_dx_result, tf_dy_result; + char string[BCTEXTLEN]; + sprintf(string, "%s%06jd", MOTION_FILE, plugin->config.track_frame); + FILE *input = fopen(string, "r"); + if(input) + { + fscanf(input, + "%d %d", + &tf_dx_result, + &tf_dy_result); + dx_result += tf_dx_result; + dy_result += tf_dy_result; + fclose(input); + } + } + + } + + + + + + +// Write results + if(plugin->config.mode2 == MotionCVConfig::SAVE) + { + char string[BCTEXTLEN]; + sprintf(string, + "%s%06jd", + MOTION_FILE, + plugin->get_source_position()); + FILE *output = fopen(string, "w"); + if(output) + { + fprintf(output, + "%d %d\n", + dx_result, + dy_result); + fclose(output); + } + else + { + perror("MotionCVScan::scan_frame SAVE 1"); + } + } + +#ifdef DEBUG +printf("MotionCVScan::scan_frame 10 dx=%.2f dy=%.2f\n", +(float)this->dx_result / OVERSAMPLE, +(float)this->dy_result / OVERSAMPLE); +#endif +} + + + + + + + + + + + + + + + + + +int64_t MotionCVScan::get_cache(int x, int y) +{ + int64_t result = -1; + cache_lock->lock("MotionCVScan::get_cache"); + for(int i = 0; i < cache.total; i++) + { + MotionCVScanCache *ptr = cache.values[i]; + if(ptr->x == x && ptr->y == y) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void MotionCVScan::put_cache(int x, int y, int64_t difference) +{ + MotionCVScanCache *ptr = new MotionCVScanCache(x, y, difference); + cache_lock->lock("MotionCVScan::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + + + +MotionCVScanCache::MotionCVScanCache(int x, int y, int64_t difference) +{ + this->x = x; + this->y = y; + this->difference = difference; +} + + + + + + + + + + + + + + +RotateCVScanPackage::RotateCVScanPackage() +{ +} + + +RotateCVScanUnit::RotateCVScanUnit(RotateCVScan *server, MotionCVMain *plugin) + : LoadClient(server) +{ + this->server = server; + this->plugin = plugin; + rotater = 0; + temp = 0; +} + +RotateCVScanUnit::~RotateCVScanUnit() +{ + delete rotater; + delete temp; +} + +void RotateCVScanUnit::process_package(LoadPackage *package) +{ + if(server->skip) return; + RotateCVScanPackage *pkg = (RotateCVScanPackage*)package; + + if((pkg->difference = server->get_cache(pkg->angle)) < 0) + { +//printf("RotateCVScanUnit::process_package 1\n"); + int color_model = server->previous_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = server->previous_frame->get_bytes_per_line(); + + if(!rotater) + rotater = new AffineEngine(1, 1); + if(!temp) temp = new VFrame( + server->previous_frame->get_w(), + server->previous_frame->get_h(), + color_model); + + +// RotateCV original block size + rotater->set_viewport(server->block_x1, + server->block_y1, + server->block_x2 - server->block_x1, + server->block_y2 - server->block_y1); + rotater->set_pivot(server->block_x, server->block_y); +//pkg->angle = 2; + rotater->rotate(temp, + server->previous_frame, + pkg->angle); +// Clamp coordinates + int x1 = server->scan_x; + int y1 = server->scan_y; + int x2 = x1 + server->scan_w; + int y2 = y1 + server->scan_h; + x2 = MIN(temp->get_w(), x2); + y2 = MIN(temp->get_h(), y2); + x2 = MIN(server->current_frame->get_w(), x2); + y2 = MIN(server->current_frame->get_h(), y2); + x1 = MAX(0, x1); + y1 = MAX(0, y1); + + if(x2 > x1 && y2 > y1) + { + pkg->difference = plugin->abs_diff( + temp->get_rows()[y1] + x1 * pixel_size, + server->current_frame->get_rows()[y1] + x1 * pixel_size, + row_bytes, + x2 - x1, + y2 - y1, + color_model); +//printf("RotateCVScanUnit::process_package %d\n", __LINE__); + server->put_cache(pkg->angle, pkg->difference); + } + +// printf("RotateCVScanUnit::process_package 10 x=%d y=%d w=%d h=%d block_x=%d block_y=%d angle=%f scan_w=%d scan_h=%d diff=%lld\n", +// server->block_x1, +// server->block_y1, +// server->block_x2 - server->block_x1, +// server->block_y2 - server->block_y1, +// server->block_x, +// server->block_y, +// pkg->angle, +// server->scan_w, +// server->scan_h, +// pkg->difference); + } +} + + + + + + + + + + + + + + + + + + + + + + +RotateCVScan::RotateCVScan(MotionCVMain *plugin, + int total_clients, + int total_packages) + : LoadServer( +//1, 1 +total_clients, total_packages +) +{ + this->plugin = plugin; + cache_lock = new Mutex("RotateCVScan::cache_lock"); +} + + +RotateCVScan::~RotateCVScan() +{ + delete cache_lock; +} + +void RotateCVScan::init_packages() +{ + for(int i = 0; i < get_total_packages(); i++) + { + RotateCVScanPackage *pkg = (RotateCVScanPackage*)get_package(i); + pkg->angle = i * + (scan_angle2 - scan_angle1) / + (total_steps - 1) + + scan_angle1; + } +} + +LoadClient* RotateCVScan::new_client() +{ + return new RotateCVScanUnit(this, plugin); +} + +LoadPackage* RotateCVScan::new_package() +{ + return new RotateCVScanPackage; +} + + +float RotateCVScan::scan_frame(VFrame *previous_frame, + VFrame *current_frame, + int block_x, + int block_y) +{ + skip = 0; + this->block_x = block_x; + this->block_y = block_y; + + switch(plugin->config.mode2) + { + case MotionCVConfig::NO_CALCULATE: + result = 0; + skip = 1; + break; + + case MotionCVConfig::LOAD: + { + char string[BCTEXTLEN]; + sprintf(string, "%s%06jd", ROTATION_FILE, plugin->get_source_position()); + FILE *input = fopen(string, "r"); + if(input) + { + fscanf(input, "%f", &result); + fclose(input); + skip = 1; + } + else + { + perror("RotateCVScan::scan_frame LOAD"); + } + break; + } + } + + + + + + + + + this->previous_frame = previous_frame; + this->current_frame = current_frame; + int w = current_frame->get_w(); + int h = current_frame->get_h(); + int block_w = w * plugin->config.rotation_block_w / 100; + int block_h = h * plugin->config.rotation_block_h / 100; + + if(this->block_x - block_w / 2 < 0) block_w = this->block_x * 2; + if(this->block_y - block_h / 2 < 0) block_h = this->block_y * 2; + if(this->block_x + block_w / 2 > w) block_w = (w - this->block_x) * 2; + if(this->block_y + block_h / 2 > h) block_h = (h - this->block_y) * 2; + + block_x1 = this->block_x - block_w / 2; + block_x2 = this->block_x + block_w / 2; + block_y1 = this->block_y - block_h / 2; + block_y2 = this->block_y + block_h / 2; + + +// Calculate the maximum area available to scan after rotation. +// Must be calculated from the starting range because of cache. +// Get coords of rectangle after rotation. + double center_x = this->block_x; + double center_y = this->block_y; + double max_angle = plugin->config.rotation_range; + double base_angle1 = atan((float)block_h / block_w); + double base_angle2 = atan((float)block_w / block_h); + double target_angle1 = base_angle1 + max_angle * 2 * M_PI / 360; + double target_angle2 = base_angle2 + max_angle * 2 * M_PI / 360; + double radius = sqrt(block_w * block_w + block_h * block_h) / 2; + double x1 = center_x - cos(target_angle1) * radius; + double y1 = center_y - sin(target_angle1) * radius; + double x2 = center_x + sin(target_angle2) * radius; + double y2 = center_y - cos(target_angle2) * radius; + double x3 = center_x - sin(target_angle2) * radius; + double y3 = center_y + cos(target_angle2) * radius; + +// Track top edge to find greatest area. + double max_area1 = 0; + //double max_x1 = 0; + double max_y1 = 0; + for(double x = x1; x < x2; x++) + { + double y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); + if(x >= center_x && x < block_x2 && y >= block_y1 && y < center_y) + { + double area = fabs(x - center_x) * fabs(y - center_y); + if(area > max_area1) + { + max_area1 = area; + //max_x1 = x; + max_y1 = y; + } + } + } + +// Track left edge to find greatest area. + double max_area2 = 0; + double max_x2 = 0; + //double max_y2 = 0; + for(double y = y1; y < y3; y++) + { + double x = x1 + (x3 - x1) * (y - y1) / (y3 - y1); + if(x >= block_x1 && x < center_x && y >= block_y1 && y < center_y) + { + double area = fabs(x - center_x) * fabs(y - center_y); + if(area > max_area2) + { + max_area2 = area; + max_x2 = x; + //max_y2 = y; + } + } + } + + double max_x, max_y; + max_x = max_x2; + max_y = max_y1; + +// Get reduced scan coords + scan_w = (int)(fabs(max_x - center_x) * 2); + scan_h = (int)(fabs(max_y - center_y) * 2); + scan_x = (int)(center_x - scan_w / 2); + scan_y = (int)(center_y - scan_h / 2); +// printf("RotateCVScan::scan_frame center=%d,%d scan=%d,%d %dx%d\n", +// this->block_x, this->block_y, scan_x, scan_y, scan_w, scan_h); +// printf(" angle_range=%f block= %d,%d,%d,%d\n", max_angle, block_x1, block_y1, block_x2, block_y2); + +// Determine min angle from size of block + double angle1 = atan((double)block_h / block_w); + double angle2 = atan((double)(block_h - 1) / (block_w + 1)); + double min_angle = fabs(angle2 - angle1) / OVERSAMPLE; + min_angle = MAX(min_angle, MIN_ANGLE); + +#ifdef DEBUG +printf("RotateCVScan::scan_frame min_angle=%f\n", min_angle * 360 / 2 / M_PI); +#endif + + cache.remove_all_objects(); + if(!skip) + { +// Initial search range + float angle_range = (float)plugin->config.rotation_range; + result = 0; + total_steps = plugin->config.rotate_positions; + + + while(angle_range >= min_angle * total_steps) + { + scan_angle1 = result - angle_range; + scan_angle2 = result + angle_range; + + + set_package_count(total_steps); +//set_package_count(1); + process_packages(); + + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + RotateCVScanPackage *pkg = (RotateCVScanPackage*)get_package(i); + if(pkg->difference < min_difference || min_difference == -1) + { + min_difference = pkg->difference; + result = pkg->angle; + } +//break; + } + + angle_range /= 2; + +//break; + } + } + + + if(!skip && plugin->config.mode2 == MotionCVConfig::SAVE) + { + char string[BCTEXTLEN]; + sprintf(string, + "%s%06jd", + ROTATION_FILE, + plugin->get_source_position()); + FILE *output = fopen(string, "w"); + if(output) + { + fprintf(output, "%f\n", result); + fclose(output); + } + else + { + perror("RotateCVScan::scan_frame SAVE"); + } + } + +#ifdef DEBUG +printf("RotateCVScan::scan_frame 10 angle=%f\n", result); +#endif + + + + return result; +} + +int64_t RotateCVScan::get_cache(float angle) +{ + int64_t result = -1; + cache_lock->lock("RotateCVScan::get_cache"); + for(int i = 0; i < cache.total; i++) + { + RotateCVScanCache *ptr = cache.values[i]; + if(fabs(ptr->angle - angle) <= MIN_ANGLE) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void RotateCVScan::put_cache(float angle, int64_t difference) +{ + RotateCVScanCache *ptr = new RotateCVScanCache(angle, difference); + cache_lock->lock("RotateCVScan::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + + + + + + + +RotateCVScanCache::RotateCVScanCache(float angle, int64_t difference) +{ + this->angle = angle; + this->difference = difference; +} + + + diff --git a/cinelerra-5.1/plugins/motion-cv/motion-cv.h b/cinelerra-5.1/plugins/motion-cv/motion-cv.h new file mode 100644 index 00000000..c8788a02 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/motion-cv.h @@ -0,0 +1,494 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +#ifndef MOTION_H +#define MOTION_H + +#include +#include +#include + +#include "affine.inc" +#include "bchash.inc" +#include "filexml.inc" +#include "keyframe.inc" +#include "loadbalance.h" +#include "overlayframe.inc" +#include "pluginvclient.h" +#include "rotateframe.inc" +#include "vframe.inc" + +class MotionCVMain; +class MotionCVWindow; +class MotionCVScan; +class RotateCVScan; + + +#define OVERSAMPLE 4 + + +// Limits of global range in percent +#define MIN_RADIUS 1 +#define MAX_RADIUS 50 + +// Limits of rotation range in degrees +#define MIN_ROTATION 1 +#define MAX_ROTATION 25 + +// Limits of block size in percent. +#define MIN_BLOCK 1 +#define MAX_BLOCK 100 + +// Limits of block count +#define MIN_BLOCKS 1 +#define MAX_BLOCKS 200 + +// Precision of rotation +#define MIN_ANGLE 0.0001 + +#define TRACKING_FILE "/tmp/motion" + +class MotionCVConfig +{ +public: + MotionCVConfig(); + + int equivalent(MotionCVConfig &that); + void copy_from(MotionCVConfig &that); + void interpolate(MotionCVConfig &prev, MotionCVConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame); + void boundaries(); + + int block_count; + int global_range_w; + int global_range_h; + int rotation_range; + int magnitude; + int return_speed; + int draw_vectors; +// Percent of image size + int global_block_w; + int global_block_h; + int rotation_block_w; + int rotation_block_h; +// Number of search positions in each refinement of the log search + int global_positions; + int rotate_positions; +// Block position in percentage 0 - 100 + double block_x; + double block_y; + + int horizontal_only; + int vertical_only; + int global; + int rotate; + int addtrackedframeoffset; + char tracking_file[BCTEXTLEN]; +// Track or stabilize, single pixel, scan only, or nothing + int mode1; +// Recalculate, no calculate, save, or load coordinates from disk + int mode2; +// Track a single frame, previous frame, or previous frame same block + int mode3; + enum + { +// mode1 + TRACK, + STABILIZE, + TRACK_PIXEL, + STABILIZE_PIXEL, + NOTHING, +// mode2 + RECALCULATE, + SAVE, + LOAD, + NO_CALCULATE, +// mode3 + TRACK_SINGLE, + TRACK_PREVIOUS, + PREVIOUS_SAME_BLOCK + }; +// Number of single frame to track relative to timeline start + int64_t track_frame; +// Master layer + int bottom_is_master; +}; + + + + +class MotionCVMain : public PluginVClient +{ +public: + MotionCVMain(PluginServer *server); + ~MotionCVMain(); + + int process_buffer(VFrame **frame, + int64_t start_position, + double frame_rate); + void process_global(); + void process_rotation(); + void draw_vectors(VFrame *frame); + int is_multichannel(); + int is_realtime(); + void save_data(KeyFrame *keyframe); + void read_data(KeyFrame *keyframe); + void update_gui(); +// Calculate frame to copy from and frame to move + void calculate_pointers(VFrame **frame, VFrame **src, VFrame **dst); + void allocate_temp(int w, int h, int color_model); + + PLUGIN_CLASS_MEMBERS2(MotionCVConfig) + + + int64_t abs_diff(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model); + int64_t abs_diff_sub(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model, + int sub_x, + int sub_y); + + static void clamp_scan(int w, + int h, + int *block_x1, + int *block_y1, + int *block_x2, + int *block_y2, + int *scan_x1, + int *scan_y1, + int *scan_x2, + int *scan_y2, + int use_absolute); + static void draw_pixel(VFrame *frame, int x, int y); + static void draw_line(VFrame *frame, int x1, int y1, int x2, int y2); + void draw_arrow(VFrame *frame, int x1, int y1, int x2, int y2); + +// Number of the previous reference frame on the timeline. + int64_t previous_frame_number; +// The frame compared with the previous frame to get the motion. +// It is moved to compensate for motion and copied to the previous_frame. + VFrame *temp_frame; + MotionCVScan *engine; + RotateCVScan *motion_rotate; + OverlayFrame *overlayer; + AffineEngine *rotate_engine; + +// Accumulation of all global tracks since the plugin start. +// Multiplied by OVERSAMPLE. + int total_dx; + int total_dy; + +// Rotation motion tracking + float total_angle; + +// Current motion vector for drawing vectors + int current_dx; + int current_dy; + float current_angle; + + FILE *active_fp; + char active_file[BCTEXTLEN]; + int get_line_key(const char *filename, int64_t key, char *line, int len); +// add constant frame offset values + int dx_offset, dy_offset; + int64_t tracking_frame; +// save/load result values + int save_dx, load_dx; + int save_dy, load_dy; + float save_dt, load_dt; + +// Oversampled current frame for motion estimation + int32_t *search_area; + int search_size; + + +// The layer to track motion in. + int reference_layer; +// The layer to apply motion in. + int target_layer; + +// Pointer to the source and destination of each operation. +// These are fully allocated buffers. + +// The previous reference frame for global motion tracking + VFrame *prev_global_ref; +// The current reference frame for global motion tracking + VFrame *current_global_ref; +// The input target frame for global motion tracking + VFrame *global_target_src; +// The output target frame for global motion tracking + VFrame *global_target_dst; + +// The previous reference frame for rotation tracking + VFrame *prev_rotate_ref; +// The current reference frame for rotation tracking + VFrame *current_rotate_ref; +// The input target frame for rotation tracking. + VFrame *rotate_target_src; +// The output target frame for rotation tracking. + VFrame *rotate_target_dst; + +// The output of process_buffer + VFrame *output_frame; + int w; + int h; +}; + + + + + + + + + + + + + + + + + + + + + + + + + +class MotionCVScanPackage : public LoadPackage +{ +public: + MotionCVScanPackage(); + +// For multiple blocks + int block_x1, block_y1, block_x2, block_y2; + int scan_x1, scan_y1, scan_x2, scan_y2; + int dx; + int dy; + int64_t max_difference; + int64_t min_difference; + int64_t min_pixel; + int is_border; + int valid; +// For single block + int pixel; + int64_t difference1; + int64_t difference2; +}; + +class MotionCVScanCache +{ +public: + MotionCVScanCache(int x, int y, int64_t difference); + int x, y; + int64_t difference; +}; + +class MotionCVScanUnit : public LoadClient +{ +public: + MotionCVScanUnit(MotionCVScan *server, MotionCVMain *plugin); + ~MotionCVScanUnit(); + + void process_package(LoadPackage *package); + int64_t get_cache(int x, int y); + void put_cache(int x, int y, int64_t difference); + + MotionCVScan *server; + MotionCVMain *plugin; + + ArrayList cache; + Mutex *cache_lock; +}; + +class MotionCVScan : public LoadServer +{ +public: + MotionCVScan(MotionCVMain *plugin, + int total_clients, + int total_packages); + ~MotionCVScan(); + + friend class MotionCVScanUnit; + + void init_packages(); + LoadClient* new_client(); + LoadPackage* new_package(); + +// Invoke the motion engine for a search +// Frame before motion + void scan_frame(VFrame *previous_frame, +// Frame after motion + VFrame *current_frame); + int64_t get_cache(int x, int y); + void put_cache(int x, int y, int64_t difference); + +// Change between previous frame and current frame multiplied by +// OVERSAMPLE + int dx_result; + int dy_result; + +private: + VFrame *previous_frame; +// Frame after motion + VFrame *current_frame; + MotionCVMain *plugin; + + int skip; +// For single block + int block_x1; + int block_x2; + int block_y1; + int block_y2; + int scan_x1; + int scan_y1; + int scan_x2; + int scan_y2; + int total_pixels; + int total_steps; + int subpixel; + + + ArrayList cache; + Mutex *cache_lock; +}; + + + + + + + + + + + + + +class RotateCVScanPackage : public LoadPackage +{ +public: + RotateCVScanPackage(); + float angle; + int64_t difference; +}; + +class RotateCVScanCache +{ +public: + RotateCVScanCache(float angle, int64_t difference); + float angle; + int64_t difference; +}; + +class RotateCVScanUnit : public LoadClient +{ +public: + RotateCVScanUnit(RotateCVScan *server, MotionCVMain *plugin); + ~RotateCVScanUnit(); + + void process_package(LoadPackage *package); + + RotateCVScan *server; + MotionCVMain *plugin; + AffineEngine *rotater; + VFrame *temp; +}; + +class RotateCVScan : public LoadServer +{ +public: + RotateCVScan(MotionCVMain *plugin, + int total_clients, + int total_packages); + ~RotateCVScan(); + + friend class RotateCVScanUnit; + + void init_packages(); + LoadClient* new_client(); + LoadPackage* new_package(); + +// Invoke the motion engine for a search +// Frame before rotation + float scan_frame(VFrame *previous_frame, +// Frame after rotation + VFrame *current_frame, +// Pivot + int block_x, + int block_y); + int64_t get_cache(float angle); + void put_cache(float angle, int64_t difference); + + +// Angle result + float result; + +private: + VFrame *previous_frame; +// Frame after motion + VFrame *current_frame; + + MotionCVMain *plugin; + int skip; + +// Pivot + int block_x; + int block_y; +// Block to rotate + int block_x1; + int block_x2; + int block_y1; + int block_y2; +// Area to compare + int scan_x; + int scan_y; + int scan_w; + int scan_h; +// Range of angles to compare + float scan_angle1, scan_angle2; + int total_steps; + + ArrayList cache; + Mutex *cache_lock; +}; + + + + +#endif + + + + + + diff --git a/cinelerra-5.1/plugins/motion-cv/motionwindow-cv.C b/cinelerra-5.1/plugins/motion-cv/motionwindow-cv.C new file mode 100644 index 00000000..e0e2b109 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/motionwindow-cv.C @@ -0,0 +1,1023 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 "bcdisplayinfo.h" +#include "clip.h" +#include "language.h" +#include "motion-cv.h" +#include "motionwindow-cv.h" + + + + + + + + + +MotionCVWindow::MotionCVWindow(MotionCVMain *plugin) + : PluginClientWindow(plugin, 815, 650, 815, 650, 0) +{ + this->plugin = plugin; +} + +MotionCVWindow::~MotionCVWindow() +{ +} + +void MotionCVWindow::create_objects() +{ + int x1 = 10, x = 10, y = 10; + int x2 = 410; + BC_Title *title; + + + + add_subwindow(global = new MotionCVGlobal(plugin, + this, + x1, + y)); + + add_subwindow(rotate = new MotionCVRotate(plugin, + this, + x2, + y)); + y += 50; + + add_subwindow(title = new BC_Title(x1, + y, + _("Translation search radius:\n(W/H Percent of image)"))); + add_subwindow(global_range_w = new GlobalRange(plugin, + x1 + title->get_w() + 10, + y, + &plugin->config.global_range_w)); + add_subwindow(global_range_h = new GlobalRange(plugin, + x1 + title->get_w() + 30 + global_range_w->get_w(), + y, + &plugin->config.global_range_h)); + + add_subwindow(title = new BC_Title(x2, + y, + _("Rotation search radius:\n(Degrees)"))); + add_subwindow(rotation_range = new RotationRange(plugin, + x2 + title->get_w() + 10, + y)); + + y += 50; + add_subwindow(title = new BC_Title(x1, + y, + _("Translation block size:\n(W/H Percent of image)"))); + add_subwindow(global_block_w = new BlockSize(plugin, + x1 + title->get_w() + 10, + y, + &plugin->config.global_block_w)); + add_subwindow(global_block_h = new BlockSize(plugin, + x1 + title->get_w() + 30 + global_block_w->get_w(), + y, + &plugin->config.global_block_h)); + + add_subwindow(title = new BC_Title(x2, + y, + _("Rotation block size:\n(W/H Percent of image)"))); + add_subwindow(rotation_block_w = new BlockSize(plugin, + x2 + title->get_w() + 10, + y, + &plugin->config.rotation_block_w)); + add_subwindow(rotation_block_h = new BlockSize(plugin, + x2 + title->get_w() + 30 + rotation_block_w->get_w(), + y, + &plugin->config.rotation_block_h)); + + y += 50; + add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:"))); + add_subwindow(global_search_positions = new GlobalSearchPositions(plugin, + x1 + title->get_w() + 10, + y, + 80)); + global_search_positions->create_objects(); + + add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:"))); + add_subwindow(rotation_search_positions = new RotationSearchPositions(plugin, + x2 + title->get_w() + 10, + y, + 80)); + rotation_search_positions->create_objects(); + + y += 50; + add_subwindow(title = new BC_Title(x, y, _("Translation direction:"))); + add_subwindow(mode3 = new Mode3(plugin, + this, + x + title->get_w() + 10, + y)); + mode3->create_objects(); + + y += 40; + add_subwindow(title = new BC_Title(x, y + 10, _("Block X:"))); + add_subwindow(block_x = new MotionCVBlockX(plugin, + this, + x + title->get_w() + 10, + y)); + add_subwindow(block_x_text = new MotionCVBlockXText(plugin, + this, + x + title->get_w() + 10 + block_x->get_w() + 10, + y + 10)); + + y += 40; + add_subwindow(title = new BC_Title(x, y + 10, _("Block Y:"))); + add_subwindow(block_y = new MotionCVBlockY(plugin, + this, + x + title->get_w() + 10, + y)); + add_subwindow(block_y_text = new MotionCVBlockYText(plugin, + this, + x + title->get_w() + 10 + block_y->get_w() + 10, + y + 10)); + + y += 50; + add_subwindow(title = new BC_Title(x, y + 10, _("Maximum absolute offset:"))); + add_subwindow(magnitude = new MotionCVMagnitude(plugin, + x + title->get_w() + 10, + y)); + + y += 40; + add_subwindow(title = new BC_Title(x, y + 10, _("Settling speed:"))); + add_subwindow(return_speed = new MotionCVReturnSpeed(plugin, + x + title->get_w() + 10, + y)); + + + + y += 40; + add_subwindow(vectors = new MotionCVDrawVectors(plugin, + this, + x, + y)); + + add_subwindow(title = new BC_Title(x2, y, _("Tracking file:"))); + add_subwindow(tracking_file = new MotionCVTrackingFile(plugin, + plugin->config.tracking_file, this, x2+title->get_w() + 20, y)); + + y += 40; + add_subwindow(track_single = new TrackSingleFrame(plugin, + this, + x, + y)); + add_subwindow(title = new BC_Title(x + track_single->get_w() + 20, + y, + _("Frame number:"))); + add_subwindow(track_frame_number = new TrackFrameNumber(plugin, + this, + x + track_single->get_w() + title->get_w() + 20, + y)); + add_subwindow(addtrackedframeoffset = new AddTrackedFrameOffset(plugin, + this, + x + track_single->get_w() + title->get_w() + 30, + y + track_single->get_h())); + + + y += 20; + add_subwindow(track_previous = new TrackPreviousFrame(plugin, + this, + x, + y)); + + y += 20; + add_subwindow(previous_same = new PreviousFrameSameBlock(plugin, + this, + x, + y)); + + y += 40; + //int y1 = y; + add_subwindow(title = new BC_Title(x, y, _("Master layer:"))); + add_subwindow(master_layer = new MasterLayer(plugin, + this, + x + title->get_w() + 10, + y)); + master_layer->create_objects(); + y += 30; + + + add_subwindow(title = new BC_Title(x, y, _("Action:"))); + add_subwindow(mode1 = new Mode1(plugin, + this, + x + title->get_w() + 10, + y)); + mode1->create_objects(); + y += 30; + + + + + add_subwindow(title = new BC_Title(x, y, _("Calculation:"))); + add_subwindow(mode2 = new Mode2(plugin, + this, + x + title->get_w() + 10, + y)); + mode2->create_objects(); + + + + show_window(1); +} + +void MotionCVWindow::update_mode() +{ + global_range_w->update(plugin->config.global_range_w, + MIN_RADIUS, + MAX_RADIUS); + global_range_h->update(plugin->config.global_range_h, + MIN_RADIUS, + MAX_RADIUS); + rotation_range->update(plugin->config.rotation_range, + MIN_ROTATION, + MAX_ROTATION); + vectors->update(plugin->config.draw_vectors); + tracking_file->update(plugin->config.tracking_file); + global->update(plugin->config.global); + rotate->update(plugin->config.rotate); + addtrackedframeoffset->update(plugin->config.addtrackedframeoffset); +} + + + + + + + + + + + + +GlobalRange::GlobalRange(MotionCVMain *plugin, + int x, + int y, + int *value) + : BC_IPot(x, + y, + (int64_t)*value, + (int64_t)MIN_RADIUS, + (int64_t)MAX_RADIUS) +{ + this->plugin = plugin; + this->value = value; +} + + +int GlobalRange::handle_event() +{ + *value = (int)get_value(); + plugin->send_configure_change(); + return 1; +} + + + + +RotationRange::RotationRange(MotionCVMain *plugin, + int x, + int y) + : BC_IPot(x, + y, + (int64_t)plugin->config.rotation_range, + (int64_t)MIN_ROTATION, + (int64_t)MAX_ROTATION) +{ + this->plugin = plugin; +} + + +int RotationRange::handle_event() +{ + plugin->config.rotation_range = (int)get_value(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +BlockSize::BlockSize(MotionCVMain *plugin, + int x, + int y, + int *value) + : BC_IPot(x, + y, + (int64_t)*value, + (int64_t)MIN_BLOCK, + (int64_t)MAX_BLOCK) +{ + this->plugin = plugin; + this->value = value; +} + + +int BlockSize::handle_event() +{ + *value = (int)get_value(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + + + + + + +GlobalSearchPositions::GlobalSearchPositions(MotionCVMain *plugin, + int x, + int y, + int w) + : BC_PopupMenu(x, + y, + w, + "", + 1) +{ + this->plugin = plugin; +} +void GlobalSearchPositions::create_objects() +{ + add_item(new BC_MenuItem("64")); + add_item(new BC_MenuItem("128")); + add_item(new BC_MenuItem("256")); + add_item(new BC_MenuItem("512")); + add_item(new BC_MenuItem("1024")); + add_item(new BC_MenuItem("2048")); + add_item(new BC_MenuItem("4096")); + add_item(new BC_MenuItem("8192")); + add_item(new BC_MenuItem("16384")); + add_item(new BC_MenuItem("32768")); + add_item(new BC_MenuItem("65536")); + add_item(new BC_MenuItem("131072")); + char string[BCTEXTLEN]; + sprintf(string, "%d", plugin->config.global_positions); + set_text(string); +} + +int GlobalSearchPositions::handle_event() +{ + plugin->config.global_positions = atoi(get_text()); + plugin->send_configure_change(); + return 1; +} + + + + + + + +RotationSearchPositions::RotationSearchPositions(MotionCVMain *plugin, + int x, + int y, + int w) + : BC_PopupMenu(x, + y, + w, + "", + 1) +{ + this->plugin = plugin; +} +void RotationSearchPositions::create_objects() +{ + add_item(new BC_MenuItem("4")); + add_item(new BC_MenuItem("8")); + add_item(new BC_MenuItem("16")); + add_item(new BC_MenuItem("32")); + char string[BCTEXTLEN]; + sprintf(string, "%d", plugin->config.rotate_positions); + set_text(string); +} + +int RotationSearchPositions::handle_event() +{ + plugin->config.rotate_positions = atoi(get_text()); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +MotionCVMagnitude::MotionCVMagnitude(MotionCVMain *plugin, + int x, + int y) + : BC_IPot(x, + y, + (int64_t)plugin->config.magnitude, + (int64_t)0, + (int64_t)100) +{ + this->plugin = plugin; +} + +int MotionCVMagnitude::handle_event() +{ + plugin->config.magnitude = (int)get_value(); + plugin->send_configure_change(); + return 1; +} + + +MotionCVReturnSpeed::MotionCVReturnSpeed(MotionCVMain *plugin, + int x, + int y) + : BC_IPot(x, + y, + (int64_t)plugin->config.return_speed, + (int64_t)0, + (int64_t)100) +{ + this->plugin = plugin; +} + +int MotionCVReturnSpeed::handle_event() +{ + plugin->config.return_speed = (int)get_value(); + plugin->send_configure_change(); + return 1; +} + + + +AddTrackedFrameOffset::AddTrackedFrameOffset(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_CheckBox(x, + y, + plugin->config.addtrackedframeoffset, + _("Add (loaded) offset from tracked frame")) +{ + this->plugin = plugin; + this->gui = gui; +} + +int AddTrackedFrameOffset::handle_event() +{ + plugin->config.addtrackedframeoffset = get_value(); + plugin->send_configure_change(); + return 1; +} + +MotionCVTrackingFile::MotionCVTrackingFile(MotionCVMain *plugin, + const char *filename, MotionCVWindow *gui, int x, int y) + : BC_TextBox(x, y, 250, 1, filename) +{ + this->plugin = plugin; + this->gui = gui; +}; + +int MotionCVTrackingFile::handle_event() +{ + strcpy(plugin->config.tracking_file, get_text()); + plugin->send_configure_change(); + return 1; +} + +MotionCVGlobal::MotionCVGlobal(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_CheckBox(x, + y, + plugin->config.global, + _("Track translation")) +{ + this->plugin = plugin; + this->gui = gui; +} + +int MotionCVGlobal::handle_event() +{ + plugin->config.global = get_value(); + plugin->send_configure_change(); + return 1; +} + +MotionCVRotate::MotionCVRotate(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_CheckBox(x, + y, + plugin->config.rotate, + _("Track rotation")) +{ + this->plugin = plugin; + this->gui = gui; +} + +int MotionCVRotate::handle_event() +{ + plugin->config.rotate = get_value(); + plugin->send_configure_change(); + return 1; +} + + + + + +MotionCVBlockX::MotionCVBlockX(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_FPot(x, + y, + plugin->config.block_x, + (float)0, + (float)100) +{ + this->plugin = plugin; + this->gui = gui; +} + +int MotionCVBlockX::handle_event() +{ + plugin->config.block_x = get_value(); + gui->block_x_text->update((float)plugin->config.block_x); + plugin->send_configure_change(); + return 1; +} + + + + +MotionCVBlockY::MotionCVBlockY(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_FPot(x, + y, + (float)plugin->config.block_y, + (float)0, + (float)100) +{ + this->plugin = plugin; + this->gui = gui; +} + +int MotionCVBlockY::handle_event() +{ + plugin->config.block_y = get_value(); + gui->block_y_text->update((float)plugin->config.block_y); + plugin->send_configure_change(); + return 1; +} + +MotionCVBlockXText::MotionCVBlockXText(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_TextBox(x, + y, + 75, + 1, + (float)plugin->config.block_x) +{ + this->plugin = plugin; + this->gui = gui; + set_precision(4); +} + +int MotionCVBlockXText::handle_event() +{ + plugin->config.block_x = atof(get_text()); + gui->block_x->update(plugin->config.block_x); + plugin->send_configure_change(); + return 1; +} + + + + +MotionCVBlockYText::MotionCVBlockYText(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_TextBox(x, + y, + 75, + 1, + (float)plugin->config.block_y) +{ + this->plugin = plugin; + this->gui = gui; + set_precision(4); +} + +int MotionCVBlockYText::handle_event() +{ + plugin->config.block_y = atof(get_text()); + gui->block_y->update(plugin->config.block_y); + plugin->send_configure_change(); + return 1; +} + + + + + + + + + + + + + + + + +MotionCVDrawVectors::MotionCVDrawVectors(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_CheckBox(x, + y, + plugin->config.draw_vectors, + _("Draw vectors")) +{ + this->gui = gui; + this->plugin = plugin; +} + +int MotionCVDrawVectors::handle_event() +{ + plugin->config.draw_vectors = get_value(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +TrackSingleFrame::TrackSingleFrame(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_Radial(x, + y, + plugin->config.mode3 == MotionCVConfig::TRACK_SINGLE, + _("Track single frame")) +{ + this->plugin = plugin; + this->gui = gui; +} + +int TrackSingleFrame::handle_event() +{ + plugin->config.mode3 = MotionCVConfig::TRACK_SINGLE; + gui->track_previous->update(0); + gui->previous_same->update(0); + gui->track_frame_number->enable(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +TrackFrameNumber::TrackFrameNumber(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_TextBox(x, y, 100, 1, plugin->config.track_frame) +{ + this->plugin = plugin; + this->gui = gui; + if(plugin->config.mode3 != MotionCVConfig::TRACK_SINGLE) disable(); +} + +int TrackFrameNumber::handle_event() +{ + plugin->config.track_frame = atol(get_text()); + plugin->send_configure_change(); + return 1; +} + + + + + + + +TrackPreviousFrame::TrackPreviousFrame(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_Radial(x, + y, + plugin->config.mode3 == MotionCVConfig::TRACK_PREVIOUS, + _("Track previous frame")) +{ + this->plugin = plugin; + this->gui = gui; +} +int TrackPreviousFrame::handle_event() +{ + plugin->config.mode3 = MotionCVConfig::TRACK_PREVIOUS; + gui->track_single->update(0); + gui->previous_same->update(0); + gui->track_frame_number->disable(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +PreviousFrameSameBlock::PreviousFrameSameBlock(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y) + : BC_Radial(x, + y, + plugin->config.mode3 == MotionCVConfig::PREVIOUS_SAME_BLOCK, + _("Previous frame same block")) +{ + this->plugin = plugin; + this->gui = gui; +} +int PreviousFrameSameBlock::handle_event() +{ + plugin->config.mode3 = MotionCVConfig::PREVIOUS_SAME_BLOCK; + gui->track_single->update(0); + gui->track_previous->update(0); + gui->track_frame_number->disable(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +MasterLayer::MasterLayer(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y) + : BC_PopupMenu(x, y, calculate_w(gui), + to_text(plugin->config.bottom_is_master)) +{ + this->plugin = plugin; + this->gui = gui; +} + +int MasterLayer::handle_event() +{ + plugin->config.bottom_is_master = from_text(get_text()); + plugin->send_configure_change(); + return 1; +} + +void MasterLayer::create_objects() +{ + add_item(new BC_MenuItem(to_text(0))); + add_item(new BC_MenuItem(to_text(1))); +} + +int MasterLayer::from_text(char *text) +{ + if(!strcmp(text, _("Top"))) return 0; + return 1; +} + +const char* MasterLayer::to_text(int mode) +{ + return mode ? _("Bottom") : _("Top"); +} + +int MasterLayer::calculate_w(MotionCVWindow *gui) +{ + int result = 0; + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1))); + return result + 50; +} + + + + + + + + +Mode1::Mode1(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y) + : BC_PopupMenu(x, y, calculate_w(gui), + to_text(plugin->config.mode1)) +{ + this->plugin = plugin; + this->gui = gui; +} + +int Mode1::handle_event() +{ + plugin->config.mode1 = from_text(get_text()); + plugin->send_configure_change(); + return 1; +} + +void Mode1::create_objects() +{ + add_item(new BC_MenuItem(to_text(MotionCVConfig::TRACK))); + add_item(new BC_MenuItem(to_text(MotionCVConfig::TRACK_PIXEL))); + add_item(new BC_MenuItem(to_text(MotionCVConfig::STABILIZE))); + add_item(new BC_MenuItem(to_text(MotionCVConfig::STABILIZE_PIXEL))); + add_item(new BC_MenuItem(to_text(MotionCVConfig::NOTHING))); +} + +int Mode1::from_text(char *text) +{ + if(!strcmp(text, _("Track Subpixel"))) return MotionCVConfig::TRACK; + if(!strcmp(text, _("Track Pixel"))) return MotionCVConfig::TRACK_PIXEL; + if(!strcmp(text, _("Stabilize Subpixel"))) return MotionCVConfig::STABILIZE; + if(!strcmp(text, _("Stabilize Pixel"))) return MotionCVConfig::STABILIZE_PIXEL; + //if(!strcmp(text, _("Do Nothing"))) return MotionCVConfig::NOTHING; + return MotionCVConfig::NOTHING; +} + +const char* Mode1::to_text(int mode) +{ + switch(mode) { + case MotionCVConfig::TRACK: return _("Track Subpixel"); + case MotionCVConfig::TRACK_PIXEL: return _("Track Pixel"); + case MotionCVConfig::STABILIZE: return _("Stabilize Subpixel"); + case MotionCVConfig::STABILIZE_PIXEL: return _("Stabilize Pixel"); + case MotionCVConfig::NOTHING: return _("Do Nothing"); + } + return ""; +} + +int Mode1::calculate_w(MotionCVWindow *gui) +{ + int result = 0; + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::TRACK))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::TRACK_PIXEL))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::STABILIZE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::STABILIZE_PIXEL))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::NOTHING))); + return result + 50; +} + + + + + +Mode2::Mode2(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y) + : BC_PopupMenu(x, y, calculate_w(gui), + to_text(plugin->config.mode2)) +{ + this->plugin = plugin; + this->gui = gui; +} + +int Mode2::handle_event() +{ + plugin->config.mode2 = from_text(get_text()); + plugin->send_configure_change(); + return 1; +} + +void Mode2::create_objects() +{ + add_item(new BC_MenuItem(to_text(MotionCVConfig::NO_CALCULATE))); + add_item(new BC_MenuItem(to_text(MotionCVConfig::RECALCULATE))); + add_item(new BC_MenuItem(to_text(MotionCVConfig::SAVE))); + add_item(new BC_MenuItem(to_text(MotionCVConfig::LOAD))); +} + +int Mode2::from_text(char *text) +{ + if(!strcmp(text, _("Recalculate"))) return MotionCVConfig::RECALCULATE; + if(!strcmp(text, _("Save coords to tracking file"))) return MotionCVConfig::SAVE; + if(!strcmp(text, _("Load coords from tracking file"))) return MotionCVConfig::LOAD; + //if(!strcmp(text, _("Don't Calculate"))) return MotionCVConfig::NO_CALCULATE; + return MotionCVConfig::NO_CALCULATE; +} + +const char* Mode2::to_text(int mode) +{ + switch(mode) { + case MotionCVConfig::NO_CALCULATE: return _("Don't Calculate"); + case MotionCVConfig::RECALCULATE: return _("Recalculate"); + case MotionCVConfig::SAVE: return _("Save coords to tracking file"); + case MotionCVConfig::LOAD: return _("Load coords from tracking file"); + } + return ""; +} + +int Mode2::calculate_w(MotionCVWindow *gui) +{ + int result = 0; + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::NO_CALCULATE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::RECALCULATE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::SAVE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::LOAD))); + return result + 50; +} + + + + + + + + + + +Mode3::Mode3(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y) + : BC_PopupMenu(x, y, calculate_w(gui), + to_text(plugin->config.horizontal_only, plugin->config.vertical_only)) +{ + this->plugin = plugin; + this->gui = gui; +} + +int Mode3::handle_event() +{ + from_text(&plugin->config.horizontal_only, &plugin->config.vertical_only, get_text()); + plugin->send_configure_change(); + return 1; +} + +void Mode3::create_objects() +{ + add_item(new BC_MenuItem(to_text(1, 0))); + add_item(new BC_MenuItem(to_text(0, 1))); + add_item(new BC_MenuItem(to_text(0, 0))); +} + +void Mode3::from_text(int *horizontal_only, int *vertical_only, char *text) +{ + *horizontal_only = 0; + *vertical_only = 0; + if(!strcmp(text, to_text(1, 0))) *horizontal_only = 1; + if(!strcmp(text, to_text(0, 1))) *vertical_only = 1; +} + +const char* Mode3::to_text(int horizontal_only, int vertical_only) +{ + if(horizontal_only) return _("Horizontal only"); + if(vertical_only) return _("Vertical only"); + return _("Both"); +} + +int Mode3::calculate_w(MotionCVWindow *gui) +{ + int result = 0; + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0))); + return result + 50; +} + diff --git a/cinelerra-5.1/plugins/motion-cv/motionwindow-cv.h b/cinelerra-5.1/plugins/motion-cv/motionwindow-cv.h new file mode 100644 index 00000000..c3cd5f8d --- /dev/null +++ b/cinelerra-5.1/plugins/motion-cv/motionwindow-cv.h @@ -0,0 +1,360 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 "guicast.h" + +class MotionCVMain; +class MotionCVWindow; +class MotionCVScan; +class RotateCVScan; + +class MasterLayer : public BC_PopupMenu +{ +public: + MasterLayer(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionCVWindow *gui); + static int from_text(char *text); + static const char* to_text(int mode); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class Mode1 : public BC_PopupMenu +{ +public: + Mode1(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionCVWindow *gui); + static int from_text(char *text); + static const char* to_text(int mode); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class Mode2 : public BC_PopupMenu +{ +public: + Mode2(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionCVWindow *gui); + static int from_text(char *text); + static const char* to_text(int mode); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class Mode3 : public BC_PopupMenu +{ +public: + Mode3(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionCVWindow *gui); + static void from_text(int *horizontal_only, int *vertical_only, char *text); + static const char* to_text(int horizontal_only, int vertical_only); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + + +class TrackSingleFrame : public BC_Radial +{ +public: + TrackSingleFrame(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class TrackFrameNumber : public BC_TextBox +{ +public: + TrackFrameNumber(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class TrackPreviousFrame : public BC_Radial +{ +public: + TrackPreviousFrame(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class PreviousFrameSameBlock : public BC_Radial +{ +public: + PreviousFrameSameBlock(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class GlobalRange : public BC_IPot +{ +public: + GlobalRange(MotionCVMain *plugin, + int x, + int y, + int *value); + int handle_event(); + MotionCVMain *plugin; + int *value; +}; + +class RotationRange : public BC_IPot +{ +public: + RotationRange(MotionCVMain *plugin, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; +}; + +class BlockSize : public BC_IPot +{ +public: + BlockSize(MotionCVMain *plugin, + int x, + int y, + int *value); + int handle_event(); + MotionCVMain *plugin; + int *value; +}; + +class MotionCVBlockX : public BC_FPot +{ +public: + MotionCVBlockX(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVWindow *gui; + MotionCVMain *plugin; +}; + +class MotionCVBlockY : public BC_FPot +{ +public: + MotionCVBlockY(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVWindow *gui; + MotionCVMain *plugin; +}; + +class MotionCVBlockXText : public BC_TextBox +{ +public: + MotionCVBlockXText(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVWindow *gui; + MotionCVMain *plugin; +}; + +class MotionCVBlockYText : public BC_TextBox +{ +public: + MotionCVBlockYText(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVWindow *gui; + MotionCVMain *plugin; +}; + +class GlobalSearchPositions : public BC_PopupMenu +{ +public: + GlobalSearchPositions(MotionCVMain *plugin, + int x, + int y, + int w); + void create_objects(); + int handle_event(); + MotionCVMain *plugin; +}; + +class RotationSearchPositions : public BC_PopupMenu +{ +public: + RotationSearchPositions(MotionCVMain *plugin, + int x, + int y, + int w); + void create_objects(); + int handle_event(); + MotionCVMain *plugin; +}; + +class MotionCVMagnitude : public BC_IPot +{ +public: + MotionCVMagnitude(MotionCVMain *plugin, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; +}; + +class MotionCVReturnSpeed : public BC_IPot +{ +public: + MotionCVReturnSpeed(MotionCVMain *plugin, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; +}; + + + +class MotionCVDrawVectors : public BC_CheckBox +{ +public: + MotionCVDrawVectors(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class AddTrackedFrameOffset : public BC_CheckBox +{ +public: + AddTrackedFrameOffset(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVWindow *gui; + MotionCVMain *plugin; +}; + +class MotionCVTrackingFile : public BC_TextBox +{ +public: + MotionCVTrackingFile(MotionCVMain *plugin, const char *filename, + MotionCVWindow *gui, int x, int y); + int handle_event(); + MotionCVMain *plugin; + MotionCVWindow *gui; +}; + +class MotionCVGlobal : public BC_CheckBox +{ +public: + MotionCVGlobal(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVWindow *gui; + MotionCVMain *plugin; +}; + +class MotionCVRotate : public BC_CheckBox +{ +public: + MotionCVRotate(MotionCVMain *plugin, + MotionCVWindow *gui, + int x, + int y); + int handle_event(); + MotionCVWindow *gui; + MotionCVMain *plugin; +}; + + + +class MotionCVWindow : public PluginClientWindow +{ +public: + MotionCVWindow(MotionCVMain *plugin); + ~MotionCVWindow(); + + void create_objects(); + void update_mode(); + char* get_radius_title(); + + GlobalRange *global_range_w; + GlobalRange *global_range_h; + RotationRange *rotation_range; + BlockSize *global_block_w; + BlockSize *global_block_h; + BlockSize *rotation_block_w; + BlockSize *rotation_block_h; + MotionCVBlockX *block_x; + MotionCVBlockY *block_y; + MotionCVBlockXText *block_x_text; + MotionCVBlockYText *block_y_text; + GlobalSearchPositions *global_search_positions; + RotationSearchPositions *rotation_search_positions; + MotionCVMagnitude *magnitude; + MotionCVReturnSpeed *return_speed; + Mode1 *mode1; + MotionCVDrawVectors *vectors; + MotionCVTrackingFile *tracking_file; + MotionCVGlobal *global; + MotionCVRotate *rotate; + AddTrackedFrameOffset *addtrackedframeoffset; + TrackSingleFrame *track_single; + TrackFrameNumber *track_frame_number; + TrackPreviousFrame *track_previous; + PreviousFrameSameBlock *previous_same; + MasterLayer *master_layer; + Mode2 *mode2; + Mode3 *mode3; + + MotionCVMain *plugin; +}; + + diff --git a/cinelerra-5.1/plugins/motion-cv/picon.png b/cinelerra-5.1/plugins/motion-cv/picon.png new file mode 100644 index 00000000..a854b23e Binary files /dev/null and b/cinelerra-5.1/plugins/motion-cv/picon.png differ diff --git a/cinelerra-5.1/plugins/motion-hv/Makefile b/cinelerra-5.1/plugins/motion-hv/Makefile new file mode 100644 index 00000000..695fd5ee --- /dev/null +++ b/cinelerra-5.1/plugins/motion-hv/Makefile @@ -0,0 +1,14 @@ +include ../../plugin_defs + +OBJS := \ + $(OBJDIR)/motion-hv.o \ + $(OBJDIR)/motionscan-hv.o \ + $(OBJDIR)/motionwindow-hv.o + +PLUGIN = motion-hv + +include ../../plugin_config + +$(OBJDIR)/motion-hv.o: motion-hv.C +$(OBJDIR)/motionscan-hv.o: motionscan-hv.C +$(OBJDIR)/motionwindow-hv.o: motionwindow-hv.C diff --git a/cinelerra-5.1/plugins/motion.new/motion.C b/cinelerra-5.1/plugins/motion-hv/motion-hv.C similarity index 60% rename from cinelerra-5.1/plugins/motion.new/motion.C rename to cinelerra-5.1/plugins/motion-hv/motion-hv.C index 81d9705b..3b0b128a 100644 --- a/cinelerra-5.1/plugins/motion.new/motion.C +++ b/cinelerra-5.1/plugins/motion-hv/motion-hv.C @@ -1,7 +1,7 @@ /* * CINELERRA - * Copyright (C) 2008 Adam Williams + * Copyright (C) 2016 Adam Williams * * 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 @@ -27,9 +27,9 @@ #include "filexml.h" #include "keyframe.h" #include "language.h" -#include "motion.h" -#include "motionscan.h" -#include "motionwindow.h" +#include "motion-hv.h" +#include "motionscan-hv.h" +#include "motionwindow-hv.h" #include "mutex.h" #include "overlayframe.h" #include "rotateframe.h" @@ -39,7 +39,7 @@ #include #include -REGISTER_PLUGIN(MotionMain) +REGISTER_PLUGIN(MotionHVMain) #undef DEBUG @@ -49,7 +49,7 @@ REGISTER_PLUGIN(MotionMain) -MotionConfig::MotionConfig() +MotionHVConfig::MotionHVConfig() { global_range_w = 5; global_range_h = 5; @@ -58,29 +58,29 @@ MotionConfig::MotionConfig() block_count = 1; global_block_w = MIN_BLOCK; global_block_h = MIN_BLOCK; - rotation_block_w = MIN_BLOCK; - rotation_block_h = MIN_BLOCK; +// rotation_block_w = MIN_BLOCK; +// rotation_block_h = MIN_BLOCK; block_x = 50; block_y = 50; - global_positions = 256; - rotate_positions = 4; +// global_positions = 256; +// rotate_positions = 4; magnitude = 100; rotate_magnitude = 90; return_speed = 0; rotate_return_speed = 0; - action_type = MotionScan::STABILIZE; - global = 1; + action_type = MotionHVScan::STABILIZE; +// global = 1; rotate = 1; - tracking_type = MotionScan::NO_CALCULATE; + tracking_type = MotionHVScan::NO_CALCULATE; draw_vectors = 1; - tracking_object = MotionScan::TRACK_SINGLE; + tracking_object = MotionHVScan::TRACK_SINGLE; track_frame = 0; bottom_is_master = 1; horizontal_only = 0; vertical_only = 0; } -void MotionConfig::boundaries() +void MotionHVConfig::boundaries() { CLAMP(global_range_w, MIN_RADIUS, MAX_RADIUS); CLAMP(global_range_h, MIN_RADIUS, MAX_RADIUS); @@ -89,29 +89,29 @@ void MotionConfig::boundaries() CLAMP(block_count, MIN_BLOCKS, MAX_BLOCKS); CLAMP(global_block_w, MIN_BLOCK, MAX_BLOCK); CLAMP(global_block_h, MIN_BLOCK, MAX_BLOCK); - CLAMP(rotation_block_w, MIN_BLOCK, MAX_BLOCK); - CLAMP(rotation_block_h, MIN_BLOCK, MAX_BLOCK); +// CLAMP(rotation_block_w, MIN_BLOCK, MAX_BLOCK); +// CLAMP(rotation_block_h, MIN_BLOCK, MAX_BLOCK); } -int MotionConfig::equivalent(MotionConfig &that) +int MotionHVConfig::equivalent(MotionHVConfig &that) { return global_range_w == that.global_range_w && global_range_h == that.global_range_h && rotation_range == that.rotation_range && rotation_center == that.rotation_center && action_type == that.action_type && - global == that.global && +// global == that.global && rotate == that.rotate && draw_vectors == that.draw_vectors && block_count == that.block_count && global_block_w == that.global_block_w && global_block_h == that.global_block_h && - rotation_block_w == that.rotation_block_w && - rotation_block_h == that.rotation_block_h && +// rotation_block_w == that.rotation_block_w && +// rotation_block_h == that.rotation_block_h && EQUIV(block_x, that.block_x) && EQUIV(block_y, that.block_y) && - global_positions == that.global_positions && - rotate_positions == that.rotate_positions && +// global_positions == that.global_positions && +// rotate_positions == that.rotate_positions && magnitude == that.magnitude && return_speed == that.return_speed && rotate_return_speed == that.rotate_return_speed && @@ -123,26 +123,26 @@ int MotionConfig::equivalent(MotionConfig &that) vertical_only == that.vertical_only; } -void MotionConfig::copy_from(MotionConfig &that) +void MotionHVConfig::copy_from(MotionHVConfig &that) { global_range_w = that.global_range_w; global_range_h = that.global_range_h; rotation_range = that.rotation_range; rotation_center = that.rotation_center; action_type = that.action_type; - global = that.global; +// global = that.global; rotate = that.rotate; tracking_type = that.tracking_type; draw_vectors = that.draw_vectors; block_count = that.block_count; block_x = that.block_x; block_y = that.block_y; - global_positions = that.global_positions; - rotate_positions = that.rotate_positions; +// global_positions = that.global_positions; +// rotate_positions = that.rotate_positions; global_block_w = that.global_block_w; global_block_h = that.global_block_h; - rotation_block_w = that.rotation_block_w; - rotation_block_h = that.rotation_block_h; +// rotation_block_w = that.rotation_block_w; +// rotation_block_h = that.rotation_block_h; magnitude = that.magnitude; return_speed = that.return_speed; rotate_magnitude = that.rotate_magnitude; @@ -154,14 +154,14 @@ void MotionConfig::copy_from(MotionConfig &that) vertical_only = that.vertical_only; } -void MotionConfig::interpolate(MotionConfig &prev, - MotionConfig &next, +void MotionHVConfig::interpolate(MotionHVConfig &prev, + MotionHVConfig &next, int64_t prev_frame, int64_t next_frame, int64_t current_frame) { - double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); - double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); + //double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); + //double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); this->block_x = prev.block_x; this->block_y = prev.block_y; global_range_w = prev.global_range_w; @@ -169,17 +169,17 @@ void MotionConfig::interpolate(MotionConfig &prev, rotation_range = prev.rotation_range; rotation_center = prev.rotation_center; action_type = prev.action_type; - global = prev.global; +// global = prev.global; rotate = prev.rotate; tracking_type = prev.tracking_type; draw_vectors = prev.draw_vectors; block_count = prev.block_count; - global_positions = prev.global_positions; - rotate_positions = prev.rotate_positions; +// global_positions = prev.global_positions; +// rotate_positions = prev.rotate_positions; global_block_w = prev.global_block_w; global_block_h = prev.global_block_h; - rotation_block_w = prev.rotation_block_w; - rotation_block_h = prev.rotation_block_h; +// rotation_block_w = prev.rotation_block_w; +// rotation_block_h = prev.rotation_block_h; magnitude = prev.magnitude; return_speed = prev.return_speed; rotate_magnitude = prev.rotate_magnitude; @@ -209,12 +209,12 @@ void MotionConfig::interpolate(MotionConfig &prev, -MotionMain::MotionMain(PluginServer *server) +MotionHVMain::MotionHVMain(PluginServer *server) : PluginVClient(server) { engine = 0; rotate_engine = 0; - motion_rotate = 0; +// motion_rotate = 0; total_dx = 0; total_dy = 0; total_angle = 0; @@ -235,7 +235,7 @@ MotionMain::MotionMain(PluginServer *server) rotate_target_dst = 0; } -MotionMain::~MotionMain() +MotionHVMain::~MotionHVMain() { delete engine; @@ -243,7 +243,7 @@ MotionMain::~MotionMain() delete [] search_area; delete temp_frame; delete rotate_engine; - delete motion_rotate; +// delete motion_rotate; delete prev_global_ref; @@ -257,67 +257,67 @@ MotionMain::~MotionMain() delete rotate_target_dst; } -const char* MotionMain::plugin_title() { return _("Motion"); } -int MotionMain::is_realtime() { return 1; } -int MotionMain::is_multichannel() { return 1; } +const char* MotionHVMain::plugin_title() { return _("MotionHV"); } +int MotionHVMain::is_realtime() { return 1; } +int MotionHVMain::is_multichannel() { return 1; } -NEW_WINDOW_MACRO(MotionMain, MotionWindow) +NEW_WINDOW_MACRO(MotionHVMain, MotionHVWindow) -LOAD_CONFIGURATION_MACRO(MotionMain, MotionConfig) +LOAD_CONFIGURATION_MACRO(MotionHVMain, MotionHVConfig) -void MotionMain::update_gui() +void MotionHVMain::update_gui() { if(thread) { if(load_configuration()) { - thread->window->lock_window("MotionMain::update_gui"); - - char string[BCTEXTLEN]; - sprintf(string, "%d", config.global_positions); - ((MotionWindow*)thread->window)->global_search_positions->set_text(string); - sprintf(string, "%d", config.rotate_positions); - ((MotionWindow*)thread->window)->rotation_search_positions->set_text(string); - - ((MotionWindow*)thread->window)->global_block_w->update(config.global_block_w); - ((MotionWindow*)thread->window)->global_block_h->update(config.global_block_h); - ((MotionWindow*)thread->window)->rotation_block_w->update(config.rotation_block_w); - ((MotionWindow*)thread->window)->rotation_block_h->update(config.rotation_block_h); - ((MotionWindow*)thread->window)->block_x->update(config.block_x); - ((MotionWindow*)thread->window)->block_y->update(config.block_y); - ((MotionWindow*)thread->window)->block_x_text->update((float)config.block_x); - ((MotionWindow*)thread->window)->block_y_text->update((float)config.block_y); - ((MotionWindow*)thread->window)->magnitude->update(config.magnitude); - ((MotionWindow*)thread->window)->return_speed->update(config.return_speed); - ((MotionWindow*)thread->window)->rotate_magnitude->update(config.rotate_magnitude); - ((MotionWindow*)thread->window)->rotate_return_speed->update(config.rotate_return_speed); - ((MotionWindow*)thread->window)->rotation_range->update(config.rotation_range); - ((MotionWindow*)thread->window)->rotation_center->update(config.rotation_center); - - - ((MotionWindow*)thread->window)->track_single->update(config.tracking_object == MotionScan::TRACK_SINGLE); - ((MotionWindow*)thread->window)->track_frame_number->update(config.track_frame); - ((MotionWindow*)thread->window)->track_previous->update(config.tracking_object == MotionScan::TRACK_PREVIOUS); - ((MotionWindow*)thread->window)->previous_same->update(config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK); - if(config.tracking_object != MotionScan::TRACK_SINGLE) - ((MotionWindow*)thread->window)->track_frame_number->disable(); + thread->window->lock_window("MotionHVMain::update_gui"); + +// char string[BCTEXTLEN]; +// sprintf(string, "%d", config.global_positions); +// ((MotionHVWindow*)thread->window)->global_search_positions->set_text(string); +// sprintf(string, "%d", config.rotate_positions); +// ((MotionHVWindow*)thread->window)->rotation_search_positions->set_text(string); + + ((MotionHVWindow*)thread->window)->global_block_w->update(config.global_block_w); + ((MotionHVWindow*)thread->window)->global_block_h->update(config.global_block_h); +// ((MotionHVWindow*)thread->window)->rotation_block_w->update(config.rotation_block_w); +// ((MotionHVWindow*)thread->window)->rotation_block_h->update(config.rotation_block_h); + ((MotionHVWindow*)thread->window)->block_x->update(config.block_x); + ((MotionHVWindow*)thread->window)->block_y->update(config.block_y); + ((MotionHVWindow*)thread->window)->block_x_text->update((float)config.block_x); + ((MotionHVWindow*)thread->window)->block_y_text->update((float)config.block_y); + ((MotionHVWindow*)thread->window)->magnitude->update(config.magnitude); + ((MotionHVWindow*)thread->window)->return_speed->update(config.return_speed); + ((MotionHVWindow*)thread->window)->rotate_magnitude->update(config.rotate_magnitude); + ((MotionHVWindow*)thread->window)->rotate_return_speed->update(config.rotate_return_speed); + ((MotionHVWindow*)thread->window)->rotation_range->update(config.rotation_range); + ((MotionHVWindow*)thread->window)->rotation_center->update(config.rotation_center); + + + ((MotionHVWindow*)thread->window)->track_single->update(config.tracking_object == MotionHVScan::TRACK_SINGLE); + ((MotionHVWindow*)thread->window)->track_frame_number->update(config.track_frame); + ((MotionHVWindow*)thread->window)->track_previous->update(config.tracking_object == MotionHVScan::TRACK_PREVIOUS); + ((MotionHVWindow*)thread->window)->previous_same->update(config.tracking_object == MotionHVScan::PREVIOUS_SAME_BLOCK); + if(config.tracking_object != MotionHVScan::TRACK_SINGLE) + ((MotionHVWindow*)thread->window)->track_frame_number->disable(); else - ((MotionWindow*)thread->window)->track_frame_number->enable(); + ((MotionHVWindow*)thread->window)->track_frame_number->enable(); - ((MotionWindow*)thread->window)->action_type->set_text( + ((MotionHVWindow*)thread->window)->action_type->set_text( ActionType::to_text(config.action_type)); - ((MotionWindow*)thread->window)->tracking_type->set_text( + ((MotionHVWindow*)thread->window)->tracking_type->set_text( TrackingType::to_text(config.tracking_type)); - ((MotionWindow*)thread->window)->track_direction->set_text( + ((MotionHVWindow*)thread->window)->track_direction->set_text( TrackDirection::to_text(config.horizontal_only, config.vertical_only)); - ((MotionWindow*)thread->window)->master_layer->set_text( + ((MotionHVWindow*)thread->window)->master_layer->set_text( MasterLayer::to_text(config.bottom_is_master)); - ((MotionWindow*)thread->window)->update_mode(); + ((MotionHVWindow*)thread->window)->update_mode(); thread->window->unlock_window(); } } @@ -326,7 +326,7 @@ void MotionMain::update_gui() -void MotionMain::save_data(KeyFrame *keyframe) +void MotionHVMain::save_data(KeyFrame *keyframe) { FileXML output; @@ -335,12 +335,12 @@ void MotionMain::save_data(KeyFrame *keyframe) output.tag.set_title("MOTION"); output.tag.set_property("BLOCK_COUNT", config.block_count); - output.tag.set_property("GLOBAL_POSITIONS", config.global_positions); - output.tag.set_property("ROTATE_POSITIONS", config.rotate_positions); +// output.tag.set_property("GLOBAL_POSITIONS", config.global_positions); +// output.tag.set_property("ROTATE_POSITIONS", config.rotate_positions); output.tag.set_property("GLOBAL_BLOCK_W", config.global_block_w); output.tag.set_property("GLOBAL_BLOCK_H", config.global_block_h); - output.tag.set_property("ROTATION_BLOCK_W", config.rotation_block_w); - output.tag.set_property("ROTATION_BLOCK_H", config.rotation_block_h); +// output.tag.set_property("ROTATION_BLOCK_W", config.rotation_block_w); +// output.tag.set_property("ROTATION_BLOCK_H", config.rotation_block_h); output.tag.set_property("BLOCK_X", config.block_x); output.tag.set_property("BLOCK_Y", config.block_y); output.tag.set_property("GLOBAL_RANGE_W", config.global_range_w); @@ -352,7 +352,7 @@ void MotionMain::save_data(KeyFrame *keyframe) output.tag.set_property("ROTATE_MAGNITUDE", config.rotate_magnitude); output.tag.set_property("ROTATE_RETURN_SPEED", config.rotate_return_speed); output.tag.set_property("ACTION_TYPE", config.action_type); - output.tag.set_property("GLOBAL", config.global); +// output.tag.set_property("GLOBAL", config.global); output.tag.set_property("ROTATE", config.rotate); output.tag.set_property("TRACKING_TYPE", config.tracking_type); output.tag.set_property("DRAW_VECTORS", config.draw_vectors); @@ -364,11 +364,10 @@ void MotionMain::save_data(KeyFrame *keyframe) output.append_tag(); output.tag.set_title("/MOTION"); output.append_tag(); - output.append_newline(); output.terminate_string(); } -void MotionMain::read_data(KeyFrame *keyframe) +void MotionHVMain::read_data(KeyFrame *keyframe) { FileXML input; @@ -385,12 +384,12 @@ void MotionMain::read_data(KeyFrame *keyframe) if(input.tag.title_is("MOTION")) { config.block_count = input.tag.get_property("BLOCK_COUNT", config.block_count); - config.global_positions = input.tag.get_property("GLOBAL_POSITIONS", config.global_positions); - config.rotate_positions = input.tag.get_property("ROTATE_POSITIONS", config.rotate_positions); +// config.global_positions = input.tag.get_property("GLOBAL_POSITIONS", config.global_positions); +// config.rotate_positions = input.tag.get_property("ROTATE_POSITIONS", config.rotate_positions); config.global_block_w = input.tag.get_property("GLOBAL_BLOCK_W", config.global_block_w); config.global_block_h = input.tag.get_property("GLOBAL_BLOCK_H", config.global_block_h); - config.rotation_block_w = input.tag.get_property("ROTATION_BLOCK_W", config.rotation_block_w); - config.rotation_block_h = input.tag.get_property("ROTATION_BLOCK_H", config.rotation_block_h); +// config.rotation_block_w = input.tag.get_property("ROTATION_BLOCK_W", config.rotation_block_w); +// config.rotation_block_h = input.tag.get_property("ROTATION_BLOCK_H", config.rotation_block_h); config.block_x = input.tag.get_property("BLOCK_X", config.block_x); config.block_y = input.tag.get_property("BLOCK_Y", config.block_y); config.global_range_w = input.tag.get_property("GLOBAL_RANGE_W", config.global_range_w); @@ -402,7 +401,7 @@ void MotionMain::read_data(KeyFrame *keyframe) config.rotate_magnitude = input.tag.get_property("ROTATE_MAGNITUDE", config.rotate_magnitude); config.rotate_return_speed = input.tag.get_property("ROTATE_RETURN_SPEED", config.rotate_return_speed); config.action_type = input.tag.get_property("ACTION_TYPE", config.action_type); - config.global = input.tag.get_property("GLOBAL", config.global); +// config.global = input.tag.get_property("GLOBAL", config.global); config.rotate = input.tag.get_property("ROTATE", config.rotate); config.tracking_type = input.tag.get_property("TRACKING_TYPE", config.tracking_type); config.draw_vectors = input.tag.get_property("DRAW_VECTORS", config.draw_vectors); @@ -425,7 +424,7 @@ void MotionMain::read_data(KeyFrame *keyframe) -void MotionMain::allocate_temp(int w, int h, int color_model) +void MotionHVMain::allocate_temp(int w, int h, int color_model) { if(temp_frame && (temp_frame->get_w() != w || @@ -439,46 +438,54 @@ void MotionMain::allocate_temp(int w, int h, int color_model) } -void MotionMain::process_global() +void MotionHVMain::process_global() { + int w = current_global_ref->get_w(); + int h = current_global_ref->get_h(); - if(!engine) engine = new MotionScan(PluginClient::get_project_smp() + 1, + + if(!engine) engine = new MotionHVScan(PluginClient::get_project_smp() + 1, PluginClient::get_project_smp() + 1); // Determine if frames changed +// printf("MotionHVMain::process_global %d block_y=%f total_dy=%d\n", +// __LINE__, config.block_y * h / 100, total_dy); engine->scan_frame(current_global_ref, prev_global_ref, - config.global_range_w, - config.global_range_h, - config.global_block_w, - config.global_block_h, - config.block_x, - config.block_y, + config.global_range_w * w / 100, + config.global_range_h * h / 100, + config.global_block_w * w / 100, + config.global_block_h * h / 100, + config.block_x * w / 100, + config.block_y * h / 100, config.tracking_object, config.tracking_type, config.action_type, config.horizontal_only, config.vertical_only, get_source_position(), - config.global_positions, total_dx, total_dy, 0, - 0); + 0, + 1, // do_motion + config.rotate, // do_rotate + config.rotation_center, + config.rotation_range); + current_dx = engine->dx_result; current_dy = engine->dy_result; // Add current motion vector to accumulation vector. - if(config.tracking_object != MotionScan::TRACK_SINGLE) + if(config.tracking_object != MotionHVScan::TRACK_SINGLE) { // Retract over time total_dx = (int64_t)total_dx * (100 - config.return_speed) / 100; total_dy = (int64_t)total_dy * (100 - config.return_speed) / 100; total_dx += engine->dx_result; total_dy += engine->dy_result; -// printf("MotionMain::process_global total_dx=%d engine->dx_result=%d\n", -// total_dx, -// engine->dx_result); +// printf("MotionHVMain::process_global %d total_dy=%d engine->dy_result=%d\n", +// __LINE__, total_dy, engine->dy_result); } else // Make accumulation vector current @@ -490,45 +497,29 @@ void MotionMain::process_global() // Clamp accumulation vector if(config.magnitude < 100) { - int block_w = (int64_t)config.global_block_w * - current_global_ref->get_w() / 100; - int block_h = (int64_t)config.global_block_h * - current_global_ref->get_h() / 100; - int block_x_orig = (int64_t)(config.block_x * - current_global_ref->get_w() / - 100); + //int block_w = (int64_t)config.global_block_w * w / 100; + //int block_h = (int64_t)config.global_block_h * h / 100; + int block_x_orig = (int64_t)(config.block_x * w / 100); int block_y_orig = (int64_t)(config.block_y * - current_global_ref->get_h() / - 100); + current_global_ref->get_h() / h / 100); - int max_block_x = (int64_t)(current_global_ref->get_w() - block_x_orig) * - OVERSAMPLE * - config.magnitude / - 100; - int max_block_y = (int64_t)(current_global_ref->get_h() - block_y_orig) * - OVERSAMPLE * - config.magnitude / - 100; + int max_block_x = (int64_t)(w - block_x_orig) * + OVERSAMPLE * config.magnitude / 100; + int max_block_y = (int64_t)(h - block_y_orig) * + OVERSAMPLE * config.magnitude / 100; int min_block_x = (int64_t)-block_x_orig * - OVERSAMPLE * - config.magnitude / - 100; + OVERSAMPLE * config.magnitude / 100; int min_block_y = (int64_t)-block_y_orig * - OVERSAMPLE * - config.magnitude / - 100; + OVERSAMPLE * config.magnitude / 100; CLAMP(total_dx, min_block_x, max_block_x); CLAMP(total_dy, min_block_y, max_block_y); } -#ifdef DEBUG -printf("MotionMain::process_global 2 total_dx=%.02f total_dy=%.02f\n", -(float)total_dx / OVERSAMPLE, -(float)total_dy / OVERSAMPLE); -#endif +// printf("MotionHVMain::process_global %d total_dx=%d total_dy=%d\n", +// __LINE__, total_dx, total_dy); - if(config.tracking_object != MotionScan::TRACK_SINGLE && !config.rotate) + if(config.tracking_object != MotionHVScan::TRACK_SINGLE && !config.rotate) { // Transfer current reference frame to previous reference frame and update // counter. Must wait for rotate to compare. @@ -537,31 +528,30 @@ printf("MotionMain::process_global 2 total_dx=%.02f total_dy=%.02f\n", } // Decide what to do with target based on requested operation - int interpolation; - float dx; - float dy; + int interpolation = NEAREST_NEIGHBOR; + float dx = 0.; + float dy = 0.; switch(config.action_type) { - case MotionScan::NOTHING: + case MotionHVScan::NOTHING: global_target_dst->copy_from(global_target_src); break; - case MotionScan::TRACK_PIXEL: + case MotionHVScan::TRACK_PIXEL: interpolation = NEAREST_NEIGHBOR; dx = (int)(total_dx / OVERSAMPLE); dy = (int)(total_dy / OVERSAMPLE); break; - case MotionScan::STABILIZE_PIXEL: + case MotionHVScan::STABILIZE_PIXEL: interpolation = NEAREST_NEIGHBOR; dx = -(int)(total_dx / OVERSAMPLE); dy = -(int)(total_dy / OVERSAMPLE); break; - break; - case MotionScan::TRACK: + case MotionHVScan::TRACK: interpolation = CUBIC_LINEAR; dx = (float)total_dx / OVERSAMPLE; dy = (float)total_dy / OVERSAMPLE; break; - case MotionScan::STABILIZE: + case MotionHVScan::STABILIZE: interpolation = CUBIC_LINEAR; dx = -(float)total_dx / OVERSAMPLE; dy = -(float)total_dy / OVERSAMPLE; @@ -569,7 +559,7 @@ printf("MotionMain::process_global 2 total_dx=%.02f total_dy=%.02f\n", } - if(config.action_type != MotionScan::NOTHING) + if(config.action_type != MotionHVScan::NOTHING) { if(!overlayer) overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); @@ -592,20 +582,22 @@ printf("MotionMain::process_global 2 total_dx=%.02f total_dy=%.02f\n", -void MotionMain::process_rotation() +void MotionHVMain::process_rotation() { int block_x; int block_y; +// Always require global // Convert the previous global reference into the previous rotation reference. // Convert global target destination into rotation target source. - if(config.global) +// if(config.global) + if(1) { if(!overlayer) overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); float dx; float dy; - if(config.tracking_object == MotionScan::TRACK_SINGLE) + if(config.tracking_object == MotionHVScan::TRACK_SINGLE) { dx = (float)total_dx / OVERSAMPLE; dy = (float)total_dy / OVERSAMPLE; @@ -644,7 +636,7 @@ void MotionMain::process_rotation() // Use the global target output as the rotation target input rotate_target_src->copy_from(global_target_dst); // Transfer current reference frame to previous reference frame for global. - if(config.tracking_object != MotionScan::TRACK_SINGLE) + if(config.tracking_object != MotionHVScan::TRACK_SINGLE) { prev_global_ref->copy_from(current_global_ref); previous_frame_number = get_source_position(); @@ -664,20 +656,20 @@ void MotionMain::process_rotation() // Get rotation - if(!motion_rotate) - motion_rotate = new RotateScan(this, - get_project_smp() + 1, - get_project_smp() + 1); - - current_angle = motion_rotate->scan_frame(prev_rotate_ref, - current_rotate_ref, - block_x, - block_y); - - +// if(!motion_rotate) +// motion_rotate = new RotateScan(this, +// get_project_smp() + 1, +// get_project_smp() + 1); +// +// current_angle = motion_rotate->scan_frame(prev_rotate_ref, +// current_rotate_ref, +// block_x, +// block_y); + + current_angle = engine->dr_result; // Add current rotation to accumulation - if(config.tracking_object != MotionScan::TRACK_SINGLE) + if(config.tracking_object != MotionHVScan::TRACK_SINGLE) { // Retract over time total_angle = total_angle * (100 - config.rotate_return_speed) / 100; @@ -690,13 +682,13 @@ void MotionMain::process_rotation() CLAMP(total_angle, -config.rotate_magnitude, config.rotate_magnitude); } - if(!config.global) - { +// if(!config.global) +// { // Transfer current reference frame to previous reference frame and update // counter. - prev_rotate_ref->copy_from(current_rotate_ref); - previous_frame_number = get_source_position(); - } +// prev_rotate_ref->copy_from(current_rotate_ref); +// previous_frame_number = get_source_position(); +// } } else { @@ -704,30 +696,30 @@ void MotionMain::process_rotation() } #ifdef DEBUG -printf("MotionMain::process_rotation total_angle=%f\n", total_angle); +printf("MotionHVMain::process_rotation total_angle=%f\n", total_angle); #endif // Calculate rotation parameters based on requested operation - float angle; + float angle = 0.; switch(config.action_type) { - case MotionScan::NOTHING: + case MotionHVScan::NOTHING: rotate_target_dst->copy_from(rotate_target_src); break; - case MotionScan::TRACK: - case MotionScan::TRACK_PIXEL: + case MotionHVScan::TRACK: + case MotionHVScan::TRACK_PIXEL: angle = total_angle; break; - case MotionScan::STABILIZE: - case MotionScan::STABILIZE_PIXEL: + case MotionHVScan::STABILIZE: + case MotionHVScan::STABILIZE_PIXEL: angle = -total_angle; break; } - if(config.action_type != MotionScan::NOTHING) + if(config.action_type != MotionHVScan::NOTHING) { if(!rotate_engine) rotate_engine = new AffineEngine(PluginClient::get_project_smp() + 1, @@ -738,17 +730,18 @@ printf("MotionMain::process_rotation total_angle=%f\n", total_angle); // Determine pivot based on a number of factors. switch(config.action_type) { - case MotionScan::TRACK: - case MotionScan::TRACK_PIXEL: + case MotionHVScan::TRACK: + case MotionHVScan::TRACK_PIXEL: // Use destination of global tracking. // rotate_engine->set_pivot(block_x, block_y); rotate_engine->set_in_pivot(block_x, block_y); rotate_engine->set_out_pivot(block_x, block_y); break; - case MotionScan::STABILIZE: - case MotionScan::STABILIZE_PIXEL: - if(config.global) + case MotionHVScan::STABILIZE: + case MotionHVScan::STABILIZE_PIXEL: +// if(config.global) + if(1) { // Use origin of global stabilize operation // rotate_engine->set_pivot((int)(rotate_target_dst->get_w() * @@ -782,6 +775,7 @@ printf("MotionMain::process_rotation total_angle=%f\n", total_angle); } +printf("MotionHVMain::process_rotation angle=%f\n", angle); rotate_engine->rotate(rotate_target_dst, rotate_target_src, angle); // overlayer->overlay(rotate_target_dst, // prev_rotate_ref, @@ -824,7 +818,7 @@ printf("MotionMain::process_rotation total_angle=%f\n", total_angle); -int MotionMain::process_buffer(VFrame **frame, +int MotionHVMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate) { @@ -835,7 +829,7 @@ int MotionMain::process_buffer(VFrame **frame, #ifdef DEBUG -printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_position); +printf("MotionHVMain::process_buffer %d start_position=%lld\n", __LINE__, start_position); #endif @@ -859,7 +853,7 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po int skip_current = 0; - if(config.tracking_object == MotionScan::TRACK_SINGLE) + if(config.tracking_object == MotionHVScan::TRACK_SINGLE) { actual_previous_number = config.track_frame; if(get_direction() == PLAY_REVERSE) @@ -903,7 +897,7 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po } - if(!config.global && !config.rotate) skip_current = 1; +// if(!config.global && !config.rotate) skip_current = 1; @@ -939,7 +933,8 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po // Get the global pointers. Here we walk through the sequence of events. - if(config.global) +// if(config.global) + if(1) { // Assume global only. Global reads previous frame and compares // with current frame to get the current translation. @@ -964,17 +959,20 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po read_frame(prev_global_ref, reference_layer, previous_frame_number, - frame_rate); + frame_rate, + 0); } read_frame(current_global_ref, reference_layer, start_position, - frame_rate); + frame_rate, + 0); read_frame(global_target_src, target_layer, start_position, - frame_rate); + frame_rate, + 0); @@ -1028,16 +1026,19 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po read_frame(prev_rotate_ref, reference_layer, previous_frame_number, - frame_rate); + frame_rate, + 0); } read_frame(current_rotate_ref, reference_layer, start_position, - frame_rate); + frame_rate, + 0); read_frame(rotate_target_src, target_layer, start_position, - frame_rate); + frame_rate, + 0); } @@ -1046,13 +1047,14 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po - +//PRINT_TRACE +//printf("skip_current=%d config.global=%d\n", skip_current, config.global); if(!skip_current) { // Get position change from previous frame to current frame - if(config.global) process_global(); + /* if(config.global) */ process_global(); // Get rotation change from previous frame to current frame if(config.rotate) process_rotation(); //frame[target_layer]->copy_from(prev_rotate_ref); @@ -1082,7 +1084,8 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po read_frame(frame[target_layer], target_layer, start_position, - frame_rate); + frame_rate, + 0); } if(config.draw_vectors) @@ -1091,14 +1094,14 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po } #ifdef DEBUG -printf("MotionMain::process_buffer %d\n", __LINE__); +printf("MotionHVMain::process_buffer %d\n", __LINE__); #endif return 0; } -void MotionMain::draw_vectors(VFrame *frame) +void MotionHVMain::draw_vectors(VFrame *frame) { int w = frame->get_w(); int h = frame->get_h(); @@ -1113,16 +1116,16 @@ void MotionMain::draw_vectors(VFrame *frame) int search_w, search_h; int search_x1, search_y1; int search_x2, search_y2; - int search_x3, search_y3; - int search_x4, search_y4; - if(config.global) +// always processing global +// if(config.global) + if(1) { // Get vector // Start of vector is center of previous block. // End of vector is total accumulation. - if(config.tracking_object == MotionScan::TRACK_SINGLE) + if(config.tracking_object == MotionHVScan::TRACK_SINGLE) { global_x1 = (int64_t)(config.block_x * w / @@ -1132,12 +1135,12 @@ void MotionMain::draw_vectors(VFrame *frame) 100); global_x2 = global_x1 + total_dx / OVERSAMPLE; global_y2 = global_y1 + total_dy / OVERSAMPLE; -//printf("MotionMain::draw_vectors %d %d %d %d %d %d\n", total_dx, total_dy, global_x1, global_y1, global_x2, global_y2); +//printf("MotionHVMain::draw_vectors %d %d %d %d %d %d\n", total_dx, total_dy, global_x1, global_y1, global_x2, global_y2); } else // Start of vector is center of previous block. // End of vector is current change. - if(config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK) + if(config.tracking_object == MotionHVScan::PREVIOUS_SAME_BLOCK) { global_x1 = (int64_t)(config.block_x * w / @@ -1187,7 +1190,7 @@ void MotionMain::draw_vectors(VFrame *frame) search_x2 = block_x2 + search_w / 2; search_y2 = block_y2 + search_h / 2; -// printf("MotionMain::draw_vectors %d %d %d %d %d %d %d %d %d %d %d %d\n", +// printf("MotionHVMain::draw_vectors %d %d %d %d %d %d %d %d %d %d %d %d\n", // global_x1, // global_y1, // block_w, @@ -1201,7 +1204,7 @@ void MotionMain::draw_vectors(VFrame *frame) // search_x2, // search_y2); - MotionScan::clamp_scan(w, + MotionHVScan::clamp_scan(w, h, &block_x1, &block_y1, @@ -1242,8 +1245,8 @@ void MotionMain::draw_vectors(VFrame *frame) block_y = (int64_t)(config.block_y * h / 100); } - block_w = config.rotation_block_w * w / 100; - block_h = config.rotation_block_h * h / 100; + block_w = config.global_block_w * w / 100; + block_h = config.global_block_h * h / 100; if(config.rotate) { float angle = total_angle * 2 * M_PI / 360; @@ -1278,7 +1281,7 @@ void MotionMain::draw_vectors(VFrame *frame) -void MotionMain::draw_pixel(VFrame *frame, int x, int y) +void MotionHVMain::draw_pixel(VFrame *frame, int x, int y) { if(!(x >= 0 && y >= 0 && x < frame->get_w() && y < frame->get_h())) return; @@ -1337,11 +1340,11 @@ void MotionMain::draw_pixel(VFrame *frame, int x, int y) } -void MotionMain::draw_line(VFrame *frame, int x1, int y1, int x2, int y2) +void MotionHVMain::draw_line(VFrame *frame, int x1, int y1, int x2, int y2) { int w = labs(x2 - x1); int h = labs(y2 - y1); -//printf("MotionMain::draw_line 1 %d %d %d %d\n", x1, y1, x2, y2); +//printf("MotionHVMain::draw_line 1 %d %d %d %d\n", x1, y1, x2, y2); if(!w && !h) { @@ -1388,11 +1391,11 @@ void MotionMain::draw_line(VFrame *frame, int x1, int y1, int x2, int y2) draw_pixel(frame, x, i); } } -//printf("MotionMain::draw_line 2\n"); +//printf("MotionHVMain::draw_line 2\n"); } #define ARROW_SIZE 10 -void MotionMain::draw_arrow(VFrame *frame, int x1, int y1, int x2, int y2) +void MotionHVMain::draw_arrow(VFrame *frame, int x1, int y1, int x2, int y2) { double angle = atan((float)(y2 - y1) / (float)(x2 - x1)); double angle1 = angle + (float)145 / 360 * 2 * 3.14159265; @@ -1434,442 +1437,3 @@ void MotionMain::draw_arrow(VFrame *frame, int x1, int y1, int x2, int y2) - - - - - - - - - -RotateScanPackage::RotateScanPackage() -{ -} - - -RotateScanUnit::RotateScanUnit(RotateScan *server, MotionMain *plugin) - : LoadClient(server) -{ - this->server = server; - this->plugin = plugin; - rotater = 0; - temp = 0; -} - -RotateScanUnit::~RotateScanUnit() -{ - delete rotater; - delete temp; -} - -void RotateScanUnit::process_package(LoadPackage *package) -{ - if(server->skip) return; - RotateScanPackage *pkg = (RotateScanPackage*)package; - - if((pkg->difference = server->get_cache(pkg->angle)) < 0) - { -//printf("RotateScanUnit::process_package %d\n", __LINE__); - int color_model = server->previous_frame->get_color_model(); - int pixel_size = BC_CModels::calculate_pixelsize(color_model); - int row_bytes = server->previous_frame->get_bytes_per_line(); - - if(!rotater) - rotater = new AffineEngine(1, 1); - if(!temp) temp = new VFrame(0, - -1, - server->previous_frame->get_w(), - server->previous_frame->get_h(), - color_model, - -1); -//printf("RotateScanUnit::process_package %d\n", __LINE__); - - -// Rotate original block size -// rotater->set_viewport(server->block_x1, -// server->block_y1, -// server->block_x2 - server->block_x1, -// server->block_y2 - server->block_y1); - rotater->set_in_viewport(server->block_x1, - server->block_y1, - server->block_x2 - server->block_x1, - server->block_y2 - server->block_y1); - rotater->set_out_viewport(server->block_x1, - server->block_y1, - server->block_x2 - server->block_x1, - server->block_y2 - server->block_y1); -// rotater->set_pivot(server->block_x, server->block_y); - rotater->set_in_pivot(server->block_x, server->block_y); - rotater->set_out_pivot(server->block_x, server->block_y); -//printf("RotateScanUnit::process_package %d\n", __LINE__); - rotater->rotate(temp, - server->previous_frame, - pkg->angle); - -// Scan reduced block size -//plugin->output_frame->copy_from(server->current_frame); -//plugin->output_frame->copy_from(temp); -// printf("RotateScanUnit::process_package %d %d %d %d %d\n", -// __LINE__, -// server->scan_x, -// server->scan_y, -// server->scan_w, -// server->scan_h); -// Clamp coordinates - int x1 = server->scan_x; - int y1 = server->scan_y; - int x2 = x1 + server->scan_w; - int y2 = y1 + server->scan_h; - x2 = MIN(temp->get_w(), x2); - y2 = MIN(temp->get_h(), y2); - x2 = MIN(server->current_frame->get_w(), x2); - y2 = MIN(server->current_frame->get_h(), y2); - x1 = MAX(0, x1); - y1 = MAX(0, y1); - - if(x2 > x1 && y2 > y1) - { - pkg->difference = MotionScan::abs_diff( - temp->get_rows()[y1] + x1 * pixel_size, - server->current_frame->get_rows()[y1] + x1 * pixel_size, - row_bytes, - x2 - x1, - y2 - y1, - color_model); -//printf("RotateScanUnit::process_package %d\n", __LINE__); - server->put_cache(pkg->angle, pkg->difference); - } - -// printf("RotateScanUnit::process_package 10 x=%d y=%d w=%d h=%d block_x=%d block_y=%d angle=%f scan_w=%d scan_h=%d diff=%lld\n", -// server->block_x1, -// server->block_y1, -// server->block_x2 - server->block_x1, -// server->block_y2 - server->block_y1, -// server->block_x, -// server->block_y, -// pkg->angle, -// server->scan_w, -// server->scan_h, -// pkg->difference); - } -} - - - - - - - - - - - - - - - - - - - - - - -RotateScan::RotateScan(MotionMain *plugin, - int total_clients, - int total_packages) - : LoadServer( -//1, 1 -total_clients, total_packages -) -{ - this->plugin = plugin; - cache_lock = new Mutex("RotateScan::cache_lock"); -} - - -RotateScan::~RotateScan() -{ - delete cache_lock; -} - -void RotateScan::init_packages() -{ - for(int i = 0; i < get_total_packages(); i++) - { - RotateScanPackage *pkg = (RotateScanPackage*)get_package(i); - pkg->angle = i * - (scan_angle2 - scan_angle1) / - (total_steps - 1) + - scan_angle1; - } -} - -LoadClient* RotateScan::new_client() -{ - return new RotateScanUnit(this, plugin); -} - -LoadPackage* RotateScan::new_package() -{ - return new RotateScanPackage; -} - - -float RotateScan::scan_frame(VFrame *previous_frame, - VFrame *current_frame, - int block_x, - int block_y) -{ - skip = 0; - this->block_x = block_x; - this->block_y = block_y; - -//printf("RotateScan::scan_frame %d\n", __LINE__); - switch(plugin->config.tracking_type) - { - case MotionScan::NO_CALCULATE: - result = plugin->config.rotation_center; - skip = 1; - break; - - case MotionScan::LOAD: - { - char string[BCTEXTLEN]; - sprintf(string, "%s%06d", ROTATION_FILE, plugin->get_source_position()); - FILE *input = fopen(string, "r"); - if(input) - { - fscanf(input, "%f", &result); - fclose(input); - skip = 1; - } - else - { - perror("RotateScan::scan_frame LOAD"); - } - break; - } - } - - - - - - - - - this->previous_frame = previous_frame; - this->current_frame = current_frame; - int w = current_frame->get_w(); - int h = current_frame->get_h(); - int block_w = w * plugin->config.rotation_block_w / 100; - int block_h = h * plugin->config.rotation_block_h / 100; - - if(this->block_x - block_w / 2 < 0) block_w = this->block_x * 2; - if(this->block_y - block_h / 2 < 0) block_h = this->block_y * 2; - if(this->block_x + block_w / 2 > w) block_w = (w - this->block_x) * 2; - if(this->block_y + block_h / 2 > h) block_h = (h - this->block_y) * 2; - - block_x1 = this->block_x - block_w / 2; - block_x2 = this->block_x + block_w / 2; - block_y1 = this->block_y - block_h / 2; - block_y2 = this->block_y + block_h / 2; - - -// Calculate the maximum area available to scan after rotation. -// Must be calculated from the starting range because of cache. -// Get coords of rectangle after rotation. - double center_x = this->block_x; - double center_y = this->block_y; - double max_angle = plugin->config.rotation_range; - double base_angle1 = atan((float)block_h / block_w); - double base_angle2 = atan((float)block_w / block_h); - double target_angle1 = base_angle1 + max_angle * 2 * M_PI / 360; - double target_angle2 = base_angle2 + max_angle * 2 * M_PI / 360; - double radius = sqrt(block_w * block_w + block_h * block_h) / 2; - double x1 = center_x - cos(target_angle1) * radius; - double y1 = center_y - sin(target_angle1) * radius; - double x2 = center_x + sin(target_angle2) * radius; - double y2 = center_y - cos(target_angle2) * radius; - double x3 = center_x - sin(target_angle2) * radius; - double y3 = center_y + cos(target_angle2) * radius; - -// Track top edge to find greatest area. - double max_area1 = 0; - double max_x1 = 0; - double max_y1 = 0; - for(double x = x1; x < x2; x++) - { - double y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); - if(x >= center_x && x < block_x2 && y >= block_y1 && y < center_y) - { - double area = fabs(x - center_x) * fabs(y - center_y); - if(area > max_area1) - { - max_area1 = area; - max_x1 = x; - max_y1 = y; - } - } - } - -// Track left edge to find greatest area. - double max_area2 = 0; - double max_x2 = 0; - double max_y2 = 0; - for(double y = y1; y < y3; y++) - { - double x = x1 + (x3 - x1) * (y - y1) / (y3 - y1); - if(x >= block_x1 && x < center_x && y >= block_y1 && y < center_y) - { - double area = fabs(x - center_x) * fabs(y - center_y); - if(area > max_area2) - { - max_area2 = area; - max_x2 = x; - max_y2 = y; - } - } - } - - double max_x, max_y; - max_x = max_x2; - max_y = max_y1; - -// Get reduced scan coords - scan_w = (int)(fabs(max_x - center_x) * 2); - scan_h = (int)(fabs(max_y - center_y) * 2); - scan_x = (int)(center_x - scan_w / 2); - scan_y = (int)(center_y - scan_h / 2); -// printf("RotateScan::scan_frame center=%d,%d scan=%d,%d %dx%d\n", -// this->block_x, this->block_y, scan_x, scan_y, scan_w, scan_h); -// printf(" angle_range=%f block= %d,%d,%d,%d\n", max_angle, block_x1, block_y1, block_x2, block_y2); - -// Determine min angle from size of block - double angle1 = atan((double)block_h / block_w); - double angle2 = atan((double)(block_h - 1) / (block_w + 1)); - double min_angle = fabs(angle2 - angle1) / OVERSAMPLE; - min_angle = MAX(min_angle, MIN_ANGLE); - -//printf("RotateScan::scan_frame %d min_angle=%f\n", __LINE__, min_angle * 360 / 2 / M_PI); - - cache.remove_all_objects(); - - - if(!skip) - { - if(previous_frame->data_matches(current_frame)) - { -//printf("RotateScan::scan_frame: frames match. Skipping.\n"); - result = plugin->config.rotation_center; - skip = 1; - } - } - - if(!skip) - { -// Initial search range - float angle_range = max_angle; - result = plugin->config.rotation_center; - total_steps = plugin->config.rotate_positions; - - - while(angle_range >= min_angle * total_steps) - { - scan_angle1 = result - angle_range; - scan_angle2 = result + angle_range; - - - set_package_count(total_steps); -//set_package_count(1); - process_packages(); - - int64_t min_difference = -1; - for(int i = 0; i < get_total_packages(); i++) - { - RotateScanPackage *pkg = (RotateScanPackage*)get_package(i); - if(pkg->difference < min_difference || min_difference == -1) - { - min_difference = pkg->difference; - result = pkg->angle; - } -//break; - } - - angle_range /= 2; - -//break; - } - } - -//printf("RotateScan::scan_frame %d\n", __LINE__); - - if(!skip && plugin->config.tracking_type == MotionScan::SAVE) - { - char string[BCTEXTLEN]; - sprintf(string, - "%s%06d", - ROTATION_FILE, - plugin->get_source_position()); - FILE *output = fopen(string, "w"); - if(output) - { - fprintf(output, "%f\n", result); - fclose(output); - } - else - { - perror("RotateScan::scan_frame SAVE"); - } - } - -//printf("RotateScan::scan_frame %d angle=%f\n", __LINE__, result); - - - - return result; -} - -int64_t RotateScan::get_cache(float angle) -{ - int64_t result = -1; - cache_lock->lock("RotateScan::get_cache"); - for(int i = 0; i < cache.total; i++) - { - RotateScanCache *ptr = cache.values[i]; - if(fabs(ptr->angle - angle) <= MIN_ANGLE) - { - result = ptr->difference; - break; - } - } - cache_lock->unlock(); - return result; -} - -void RotateScan::put_cache(float angle, int64_t difference) -{ - RotateScanCache *ptr = new RotateScanCache(angle, difference); - cache_lock->lock("RotateScan::put_cache"); - cache.append(ptr); - cache_lock->unlock(); -} - - - - - - - - - -RotateScanCache::RotateScanCache(float angle, int64_t difference) -{ - this->angle = angle; - this->difference = difference; -} - - - diff --git a/cinelerra-5.1/plugins/motion.new/motion.h b/cinelerra-5.1/plugins/motion-hv/motion-hv.h similarity index 69% rename from cinelerra-5.1/plugins/motion.new/motion.h rename to cinelerra-5.1/plugins/motion-hv/motion-hv.h index 9ace9613..f375fb43 100644 --- a/cinelerra-5.1/plugins/motion.new/motion.h +++ b/cinelerra-5.1/plugins/motion-hv/motion-hv.h @@ -1,7 +1,7 @@ /* * CINELERRA - * Copyright (C) 2008 Adam Williams + * Copyright (C) 2016 Adam Williams * * 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 @@ -31,16 +31,14 @@ #include "filexml.inc" #include "keyframe.inc" #include "loadbalance.h" -#include "motionscan.inc" -#include "motionwindow.inc" +#include "motionscan-hv.inc" +#include "motionwindow-hv.inc" #include "overlayframe.inc" #include "pluginvclient.h" -#include "rotateframe.inc" #include "vframe.inc" -class MotionMain; -class MotionWindow; -class RotateScan; +class MotionHVMain; +class MotionHVWindow; @@ -64,17 +62,16 @@ class RotateScan; // Precision of rotation #define MIN_ANGLE 0.0001 -#define ROTATION_FILE "/tmp/rotate" -class MotionConfig +class MotionHVConfig { public: - MotionConfig(); + MotionHVConfig(); - int equivalent(MotionConfig &that); - void copy_from(MotionConfig &that); - void interpolate(MotionConfig &prev, - MotionConfig &next, + int equivalent(MotionHVConfig &that); + void copy_from(MotionHVConfig &that); + void interpolate(MotionHVConfig &prev, + MotionHVConfig &next, int64_t prev_frame, int64_t next_frame, int64_t current_frame); @@ -95,11 +92,11 @@ public: // Percent of image size int global_block_w; int global_block_h; - int rotation_block_w; - int rotation_block_h; +// int rotation_block_w; +// int rotation_block_h; // Number of search positions in each refinement of the log search - int global_positions; - int rotate_positions; +// int global_positions; +// int rotate_positions; // Block position in percentage 0 - 100 double block_x; double block_y; @@ -146,11 +143,11 @@ public: -class MotionMain : public PluginVClient +class MotionHVMain : public PluginVClient { public: - MotionMain(PluginServer *server); - ~MotionMain(); + MotionHVMain(PluginServer *server); + ~MotionHVMain(); int process_buffer(VFrame **frame, int64_t start_position, @@ -167,7 +164,7 @@ public: void calculate_pointers(VFrame **frame, VFrame **src, VFrame **dst); void allocate_temp(int w, int h, int color_model); - PLUGIN_CLASS_MEMBERS2(MotionConfig) + PLUGIN_CLASS_MEMBERS2(MotionHVConfig) static void draw_pixel(VFrame *frame, int x, int y); @@ -179,8 +176,8 @@ public: // The frame compared with the previous frame to get the motion. // It is moved to compensate for motion and copied to the previous_frame. VFrame *temp_frame; - MotionScan *engine; - RotateScan *motion_rotate; + MotionHVScan *engine; +// RotateScan *motion_rotate; OverlayFrame *overlayer; AffineEngine *rotate_engine; @@ -246,110 +243,6 @@ public: - - - - - - - - - - - - - -class RotateScanPackage : public LoadPackage -{ -public: - RotateScanPackage(); - float angle; - int64_t difference; -}; - -class RotateScanCache -{ -public: - RotateScanCache(float angle, int64_t difference); - float angle; - int64_t difference; -}; - -class RotateScanUnit : public LoadClient -{ -public: - RotateScanUnit(RotateScan *server, MotionMain *plugin); - ~RotateScanUnit(); - - void process_package(LoadPackage *package); - - RotateScan *server; - MotionMain *plugin; - AffineEngine *rotater; - VFrame *temp; -}; - -class RotateScan : public LoadServer -{ -public: - RotateScan(MotionMain *plugin, - int total_clients, - int total_packages); - ~RotateScan(); - - friend class RotateScanUnit; - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - -// Invoke the motion engine for a search -// Frame before rotation - float scan_frame(VFrame *previous_frame, -// Frame after rotation - VFrame *current_frame, -// Pivot - int block_x, - int block_y); - int64_t get_cache(float angle); - void put_cache(float angle, int64_t difference); - - -// Angle result - float result; - -private: - VFrame *previous_frame; -// Frame after motion - VFrame *current_frame; - - MotionMain *plugin; - int skip; - -// Pivot - int block_x; - int block_y; -// Block to rotate - int block_x1; - int block_x2; - int block_y1; - int block_y2; -// Area to compare - int scan_x; - int scan_y; - int scan_w; - int scan_h; -// Range of angles to compare - float scan_angle1, scan_angle2; - int total_steps; - - ArrayList cache; - Mutex *cache_lock; -}; - - - - #endif diff --git a/cinelerra-5.1/plugins/motion.new/motion.inc b/cinelerra-5.1/plugins/motion-hv/motion-hv.inc similarity index 90% rename from cinelerra-5.1/plugins/motion.new/motion.inc rename to cinelerra-5.1/plugins/motion-hv/motion-hv.inc index cf71a2a4..b8b8795d 100644 --- a/cinelerra-5.1/plugins/motion.new/motion.inc +++ b/cinelerra-5.1/plugins/motion-hv/motion-hv.inc @@ -19,12 +19,12 @@ * */ -#ifndef MOTION_INC -#define MOTION_INC +#ifndef MOTIONHV_INC +#define MOTIONHV_INC -class MotionConfig; -class MotionMain; +class MotionHVConfig; +class MotionHVMain; #endif diff --git a/cinelerra-5.1/plugins/motion-hv/motionscan-hv.C b/cinelerra-5.1/plugins/motion-hv/motionscan-hv.C new file mode 100644 index 00000000..db8617ea --- /dev/null +++ b/cinelerra-5.1/plugins/motion-hv/motionscan-hv.C @@ -0,0 +1,1936 @@ + +/* + * CINELERRA + * Copyright (C) 2016 Adam Williams + * + * 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 "affine.h" +#include "bcsignals.h" +#include "clip.h" +#include "motionscan-hv.h" +#include "mutex.h" +#include "vframe.h" + + +#include +#include +#include + +// The module which does the actual scanning + +// starting level of detail +#define STARTING_DOWNSAMPLE 16 +// minimum size in each level of detail +#define MIN_DOWNSAMPLED_SIZE 16 +// minimum scan range +#define MIN_DOWNSAMPLED_SCAN 4 +// scan range for subpixel mode +#define SUBPIXEL_RANGE 4 + +MotionHVScanPackage::MotionHVScanPackage() + : LoadPackage() +{ + valid = 1; +} + + + + + + +MotionHVScanUnit::MotionHVScanUnit(MotionHVScan *server) + : LoadClient(server) +{ + this->server = server; +} + +MotionHVScanUnit::~MotionHVScanUnit() +{ +} + + +void MotionHVScanUnit::single_pixel(MotionHVScanPackage *pkg) +{ + //int w = server->current_frame->get_w(); + //int h = server->current_frame->get_h(); + int color_model = server->current_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = server->current_frame->get_bytes_per_line(); + +// printf("MotionHVScanUnit::process_package %d search_x=%d search_y=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d x_steps=%d y_steps=%d\n", +// __LINE__, +// pkg->search_x, +// pkg->search_y, +// pkg->scan_x1, +// pkg->scan_y1, +// pkg->scan_x2, +// pkg->scan_y2, +// server->x_steps, +// server->y_steps); + +// Pointers to first pixel in each block + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + pkg->search_y] + + pkg->search_x * pixel_size; + unsigned char *current_ptr = 0; + + if(server->do_rotate) + { + current_ptr = server->rotated_current[pkg->angle_step]->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; + } + else + { + current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; + } + +// Scan block + pkg->difference1 = MotionHVScan::abs_diff(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model); + +// printf("MotionHVScanUnit::process_package %d angle_step=%d diff=%d\n", +// __LINE__, +// pkg->angle_step, +// pkg->difference1); +// printf("MotionHVScanUnit::process_package %d search_x=%d search_y=%d diff=%lld\n", +// __LINE__, server->block_x1 - pkg->search_x, server->block_y1 - pkg->search_y, pkg->difference1); +} + +void MotionHVScanUnit::subpixel(MotionHVScanPackage *pkg) +{ +//PRINT_TRACE + //int w = server->current_frame->get_w(); + //int h = server->current_frame->get_h(); + int color_model = server->current_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = server->current_frame->get_bytes_per_line(); + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + pkg->search_y] + + pkg->search_x * pixel_size; +// neglect rotation + unsigned char *current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; + +// With subpixel, there are two ways to compare each position, one by shifting +// the previous frame and two by shifting the current frame. + pkg->difference1 = MotionHVScan::abs_diff_sub(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + pkg->sub_x, + pkg->sub_y); + pkg->difference2 = MotionHVScan::abs_diff_sub(current_ptr, + prev_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + pkg->sub_x, + pkg->sub_y); +// printf("MotionHVScanUnit::process_package sub_x=%d sub_y=%d search_x=%d search_y=%d diff1=%lld diff2=%lld\n", +// pkg->sub_x, +// pkg->sub_y, +// pkg->search_x, +// pkg->search_y, +// pkg->difference1, +// pkg->difference2); +} + +void MotionHVScanUnit::process_package(LoadPackage *package) +{ + MotionHVScanPackage *pkg = (MotionHVScanPackage*)package; + + +// Single pixel + if(!server->subpixel) + { + single_pixel(pkg); + } + else +// Sub pixel + { + subpixel(pkg); + } + + + + +} + + + + + + + + + + + + + + + + + + +MotionHVScan::MotionHVScan(int total_clients, + int total_packages) + : LoadServer( +// DEBUG +//1, 1 +total_clients, total_packages +) +{ + test_match = 1; + downsampled_previous = 0; + downsampled_current = 0; + rotated_current = 0; + rotater = 0; +} + +MotionHVScan::~MotionHVScan() +{ + delete downsampled_previous; + delete downsampled_current; + if(rotated_current) + { + for(int i = 0; i < total_rotated; i++) + { + delete rotated_current[i]; + } + + delete [] rotated_current; + } + delete rotater; +} + + +void MotionHVScan::init_packages() +{ +// Set package coords +// Total range of positions to scan with downsampling + int downsampled_scan_x1 = scan_x1 / current_downsample; + //int downsampled_scan_x2 = scan_x2 / current_downsample; + int downsampled_scan_y1 = scan_y1 / current_downsample; + //int downsampled_scan_y2 = scan_y2 / current_downsample; + int downsampled_block_x1 = block_x1 / current_downsample; + int downsampled_block_x2 = block_x2 / current_downsample; + int downsampled_block_y1 = block_y1 / current_downsample; + int downsampled_block_y2 = block_y2 / current_downsample; + + +//printf("MotionHVScan::init_packages %d %d\n", __LINE__, get_total_packages()); +// printf("MotionHVScan::init_packages %d current_downsample=%d scan_x1=%d scan_x2=%d block_x1=%d block_x2=%d\n", +// __LINE__, +// current_downsample, +// downsampled_scan_x1, +// downsampled_scan_x2, +// downsampled_block_x1, +// downsampled_block_x2); +// if(current_downsample == 8 && downsampled_scan_x1 == 47) +// { +// downsampled_previous->write_png("/tmp/previous"); +// downsampled_current->write_png("/tmp/current"); +// } + + for(int i = 0; i < get_total_packages(); i++) + { + MotionHVScanPackage *pkg = (MotionHVScanPackage*)get_package(i); + + pkg->block_x1 = downsampled_block_x1; + pkg->block_x2 = downsampled_block_x2; + pkg->block_y1 = downsampled_block_y1; + pkg->block_y2 = downsampled_block_y2; + pkg->difference1 = 0; + pkg->difference2 = 0; + pkg->dx = 0; + pkg->dy = 0; + pkg->valid = 1; + pkg->angle_step = 0; + + if(!subpixel) + { + if(rotation_pass) + { + pkg->search_x = scan_x1 / current_downsample; + pkg->search_y = scan_y1 / current_downsample; + pkg->angle_step = i; + } + else + { + + int current_x_step = (i % x_steps); + int current_y_step = (i / x_steps); + + //printf("MotionHVScan::init_packages %d i=%d x_step=%d y_step=%d angle_step=%d\n", + //__LINE__, i, current_x_step, current_y_step, current_angle_step); + pkg->search_x = downsampled_scan_x1 + current_x_step * + (scan_x2 - scan_x1) / current_downsample / x_steps; + pkg->search_y = downsampled_scan_y1 + current_y_step * + (scan_y2 - scan_y1) / current_downsample / y_steps; + + if(do_rotate) + { + pkg->angle_step = angle_steps / 2; + } + else + { + pkg->angle_step = 0; + } + } + + pkg->sub_x = 0; + pkg->sub_y = 0; + } + else + { + pkg->sub_x = i % (OVERSAMPLE * SUBPIXEL_RANGE); + pkg->sub_y = i / (OVERSAMPLE * SUBPIXEL_RANGE); + +// if(horizontal_only) +// { +// pkg->sub_y = 0; +// } +// +// if(vertical_only) +// { +// pkg->sub_x = 0; +// } + + pkg->search_x = scan_x1 + pkg->sub_x / OVERSAMPLE + 1; + pkg->search_y = scan_y1 + pkg->sub_y / OVERSAMPLE + 1; + pkg->sub_x %= OVERSAMPLE; + pkg->sub_y %= OVERSAMPLE; + + + +// printf("MotionHVScan::init_packages %d i=%d search_x=%d search_y=%d sub_x=%d sub_y=%d\n", +// __LINE__, +// i, +// pkg->search_x, +// pkg->search_y, +// pkg->sub_x, +// pkg->sub_y); + } + +// printf("MotionHVScan::init_packages %d %d,%d %d,%d %d,%d\n", +// __LINE__, +// scan_x1, +// scan_x2, +// scan_y1, +// scan_y2, +// pkg->search_x, +// pkg->search_y); + } +} + +LoadClient* MotionHVScan::new_client() +{ + return new MotionHVScanUnit(this); +} + +LoadPackage* MotionHVScan::new_package() +{ + return new MotionHVScanPackage; +} + + +void MotionHVScan::set_test_match(int value) +{ + this->test_match = value; +} + + + + +#define DOWNSAMPLE(type, temp_type, components, max) \ +{ \ + temp_type r; \ + temp_type g; \ + temp_type b; \ + temp_type a; \ + type **in_rows = (type**)src->get_rows(); \ + type **out_rows = (type**)dst->get_rows(); \ + \ + for(int i = 0; i < h; i += downsample) \ + { \ + int y1 = MAX(i, 0); \ + int y2 = MIN(i + downsample, h); \ + \ + \ + for(int j = 0; \ + j < w; \ + j += downsample) \ + { \ + int x1 = MAX(j, 0); \ + int x2 = MIN(j + downsample, w); \ + \ + temp_type scale = (x2 - x1) * (y2 - y1); \ + if(x2 > x1 && y2 > y1) \ + { \ + \ +/* Read in values */ \ + r = 0; \ + g = 0; \ + b = 0; \ + if(components == 4) a = 0; \ + \ + for(int k = y1; k < y2; k++) \ + { \ + type *row = in_rows[k] + x1 * components; \ + for(int l = x1; l < x2; l++) \ + { \ + r += *row++; \ + g += *row++; \ + b += *row++; \ + if(components == 4) a += *row++; \ + } \ + } \ + \ +/* Write average */ \ + r /= scale; \ + g /= scale; \ + b /= scale; \ + if(components == 4) a /= scale; \ + \ + type *row = out_rows[y1 / downsample] + \ + x1 / downsample * components; \ + *row++ = r; \ + *row++ = g; \ + *row++ = b; \ + if(components == 4) *row++ = a; \ + } \ + } \ +/*printf("DOWNSAMPLE 3 %d\n", i);*/ \ + } \ +} + + + + +void MotionHVScan::downsample_frame(VFrame *dst, + VFrame *src, + int downsample) +{ + int h = src->get_h(); + int w = src->get_w(); + +//PRINT_TRACE +//printf("downsample=%d w=%d h=%d dst=%d %d\n", downsample, w, h, dst->get_w(), dst->get_h()); + switch(src->get_color_model()) + { + case BC_RGB888: + DOWNSAMPLE(uint8_t, int64_t, 3, 0xff) + break; + case BC_RGB_FLOAT: + DOWNSAMPLE(float, float, 3, 1.0) + break; + case BC_RGBA8888: + DOWNSAMPLE(uint8_t, int64_t, 4, 0xff) + break; + case BC_RGBA_FLOAT: + DOWNSAMPLE(float, float, 4, 1.0) + break; + case BC_YUV888: + DOWNSAMPLE(uint8_t, int64_t, 3, 0xff) + break; + case BC_YUVA8888: + DOWNSAMPLE(uint8_t, int64_t, 4, 0xff) + break; + } +//PRINT_TRACE +} + +double MotionHVScan::step_to_angle(int step, double center) +{ + if(step < angle_steps / 2) + { + return center - angle_step * (angle_steps / 2 - step); + } + else + if(step > angle_steps / 2) + { + return center + angle_step * (step - angle_steps / 2); + } + else + { + return center; + } +} + +#ifdef STDDEV_TEST +static int compare(const void *p1, const void *p2) +{ + double value1 = *(double*)p1; + double value2 = *(double*)p2; + +//printf("compare %d value1=%f value2=%f\n", __LINE__, value1, value2); + return value1 > value2; +} +#endif + +// reject vectors based on content. It's the reason Goog can't stabilize timelapses. +//#define STDDEV_TEST + +// pixel accurate motion search +void MotionHVScan::pixel_search(int &x_result, int &y_result, double &r_result) +{ +// reduce level of detail until enough steps + while(current_downsample > 1 && + ((block_x2 - block_x1) / current_downsample < MIN_DOWNSAMPLED_SIZE || + (block_y2 - block_y1) / current_downsample < MIN_DOWNSAMPLED_SIZE + || + (scan_x2 - scan_x1) / current_downsample < MIN_DOWNSAMPLED_SCAN || + (scan_y2 - scan_y1) / current_downsample < MIN_DOWNSAMPLED_SCAN + )) + { + current_downsample /= 2; + } + + + +// create downsampled images. +// Need to keep entire frame to search for rotation. + int downsampled_prev_w = previous_frame_arg->get_w() / current_downsample; + int downsampled_prev_h = previous_frame_arg->get_h() / current_downsample; + int downsampled_current_w = current_frame_arg->get_w() / current_downsample; + int downsampled_current_h = current_frame_arg->get_h() / current_downsample; + +// printf("MotionHVScan::pixel_search %d current_downsample=%d current_frame_arg->get_w()=%d downsampled_current_w=%d\n", +// __LINE__, +// current_downsample, +// current_frame_arg->get_w(), +// downsampled_current_w); + + x_steps = (scan_x2 - scan_x1) / current_downsample; + y_steps = (scan_y2 - scan_y1) / current_downsample; + +// in rads + double test_angle1 = atan2((double)downsampled_current_h / 2 - 1, (double)downsampled_current_w / 2); + double test_angle2 = atan2((double)downsampled_current_h / 2, (double)downsampled_current_w / 2 - 1); + +// in deg + angle_step = 360.0f * fabs(test_angle1 - test_angle2) / 2 / M_PI; + +// printf("MotionHVScan::pixel_search %d test_angle1=%f test_angle2=%f angle_step=%f\n", +// __LINE__, +// 360.0f * test_angle1 / 2 / M_PI, +// 360.0f * test_angle2 / 2 / M_PI, +// angle_step); + + + if(do_rotate && angle_step < rotation_range) + { + angle_steps = 1 + (int)((scan_angle2 - scan_angle1) / angle_step + 0.5); + } + else + { + angle_steps = 1; + } + + + if(current_downsample > 1) + { + if(!downsampled_previous || + downsampled_previous->get_w() != downsampled_prev_w || + downsampled_previous->get_h() != downsampled_prev_h) + { + delete downsampled_previous; + downsampled_previous = new VFrame(); + downsampled_previous->set_use_shm(0); + downsampled_previous->reallocate(0, + -1, + 0, + 0, + 0, + downsampled_prev_w + 1, + downsampled_prev_h + 1, + previous_frame_arg->get_color_model(), + -1); + } + + if(!downsampled_current || + downsampled_current->get_w() != downsampled_current_w || + downsampled_current->get_h() != downsampled_current_h) + { + delete downsampled_current; + downsampled_current = new VFrame(); + downsampled_current->set_use_shm(0); + downsampled_current->reallocate(0, + -1, + 0, + 0, + 0, + downsampled_current_w + 1, + downsampled_current_h + 1, + current_frame_arg->get_color_model(), + -1); + } + + + downsample_frame(downsampled_previous, + previous_frame_arg, + current_downsample); + downsample_frame(downsampled_current, + current_frame_arg, + current_downsample); + previous_frame = downsampled_previous; + current_frame = downsampled_current; + + } + else + { + previous_frame = previous_frame_arg; + current_frame = current_frame_arg; + } + + + +// printf("MotionHVScan::pixel_search %d x_steps=%d y_steps=%d angle_steps=%d total_steps=%d\n", +// __LINE__, +// x_steps, +// y_steps, +// angle_steps, +// total_steps); + + + +// test variance of constant macroblock + int color_model = current_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = current_frame->get_bytes_per_line(); + int block_w = block_x2 - block_x1; + int block_h = block_y2 - block_y1; + + unsigned char *current_ptr = + current_frame->get_rows()[block_y1 / current_downsample] + + (block_x1 / current_downsample) * pixel_size; + unsigned char *previous_ptr = + previous_frame->get_rows()[scan_y1 / current_downsample] + + (scan_x1 / current_downsample) * pixel_size; + + + +// test detail in prev & current frame + double range1 = calculate_range(current_ptr, + row_bytes, + block_w / current_downsample, + block_h / current_downsample, + color_model); + + if(range1 < 1) + { +printf("MotionHVScan::pixel_search %d range fail range1=%f\n", __LINE__, range1); + failed = 1; + return; + } + + double range2 = calculate_range(previous_ptr, + row_bytes, + block_w / current_downsample, + block_h / current_downsample, + color_model); + + if(range2 < 1) + { +printf("MotionHVScan::pixel_search %d range fail range2=%f\n", __LINE__, range2); + failed = 1; + return; + } + + +// create rotated images + if(rotated_current && + (total_rotated != angle_steps || + rotated_current[0]->get_w() != downsampled_current_w || + rotated_current[0]->get_h() != downsampled_current_h)) + { + for(int i = 0; i < total_rotated; i++) + { + delete rotated_current[i]; + } + + delete [] rotated_current; + rotated_current = 0; + total_rotated = 0; + } + + if(do_rotate) + { + total_rotated = angle_steps; + + + if(!rotated_current) + { + rotated_current = new VFrame*[total_rotated]; + bzero(rotated_current, sizeof(VFrame*) * total_rotated); + } + +// printf("MotionHVScan::pixel_search %d total_rotated=%d w=%d h=%d block_w=%d block_h=%d\n", +// __LINE__, +// total_rotated, +// downsampled_current_w, +// downsampled_current_h, +// (block_x2 - block_x1) / current_downsample, +// (block_y2 - block_y1) / current_downsample); + for(int i = 0; i < angle_steps; i++) + { + +// printf("MotionHVScan::pixel_search %d w=%d h=%d x=%d y=%d angle=%f\n", +// __LINE__, +// downsampled_current_w, +// downsampled_current_h, +// (block_x1 + block_x2) / 2 / current_downsample, +// (block_y1 + block_y2) / 2 / current_downsample, +// step_to_angle(i, r_result)); + +// printf("MotionHVScan::pixel_search %d i=%d rotated_current[i]=%p\n", +// __LINE__, +// i, +// rotated_current[i]); + if(!rotated_current[i]) + { + rotated_current[i] = new VFrame(); + rotated_current[i]->set_use_shm(0); + rotated_current[i]->reallocate(0, + -1, + 0, + 0, + 0, + downsampled_current_w + 1, + downsampled_current_h + 1, + current_frame_arg->get_color_model(), + -1); +//printf("MotionHVScan::pixel_search %d\n", __LINE__); + } + + + if(!rotater) + { + rotater = new AffineEngine(get_total_clients(), + get_total_clients()); + } + +// get smallest viewport size required for the angle + double diag = hypot((block_x2 - block_x1) / current_downsample, + (block_y2 - block_y1) / current_downsample); + double angle1 = atan2(block_y2 - block_y1, block_x2 - block_x1) + + TO_RAD(step_to_angle(i, r_result)); + double angle2 = -atan2(block_y2 - block_y1, block_x2 - block_x1) + + TO_RAD(step_to_angle(i, r_result)); + double max_horiz = MAX(abs(diag * cos(angle1)), abs(diag * cos(angle2))); + double max_vert = MAX(abs(diag * sin(angle1)), abs(diag * sin(angle2))); + int center_x = (block_x1 + block_x2) / 2 / current_downsample; + int center_y = (block_y1 + block_y2) / 2 / current_downsample; + int x1 = center_x - max_horiz / 2; + int y1 = center_y - max_vert / 2; + int x2 = x1 + max_horiz; + int y2 = y1 + max_vert; + CLAMP(x1, 0, downsampled_current_w - 1); + CLAMP(y1, 0, downsampled_current_h - 1); + CLAMP(x2, 0, downsampled_current_w - 1); + CLAMP(y2, 0, downsampled_current_h - 1); + +//printf("MotionHVScan::pixel_search %d %f %f %d %d\n", +//__LINE__, TO_DEG(angle1), TO_DEG(angle2), (int)max_horiz, (int)max_vert); + rotater->set_in_viewport(x1, + y1, + x2 - x1, + y2 - y1); + rotater->set_out_viewport(x1, + y1, + x2 - x1, + y2 - y1); + +// rotater->set_in_viewport(0, +// 0, +// downsampled_current_w, +// downsampled_current_h); +// rotater->set_out_viewport(0, +// 0, +// downsampled_current_w, +// downsampled_current_h); + + rotater->set_in_pivot(center_x, center_y); + rotater->set_out_pivot(center_x, center_y); + + rotater->rotate(rotated_current[i], + current_frame, + step_to_angle(i, r_result)); + +// rotated_current[i]->draw_rect(block_x1 / current_downsample, +// block_y1 / current_downsample, +// block_x2 / current_downsample, +// block_y2 / current_downsample); +// char string[BCTEXTLEN]; +// sprintf(string, "/tmp/rotated%d", i); +// rotated_current[i]->write_png(string); +//downsampled_previous->write_png("/tmp/previous"); +//printf("MotionHVScan::pixel_search %d\n", __LINE__); + } + } + + + + + + +// printf("MotionHVScan::pixel_search %d block x=%d y=%d w=%d h=%d\n", +// __LINE__, +// block_x1 / current_downsample, +// block_y1 / current_downsample, +// block_w / current_downsample, +// block_h / current_downsample); + + + + + + + +//exit(1); +// Test only translation of the middle rotated frame + rotation_pass = 0; + total_steps = x_steps * y_steps; + set_package_count(total_steps); + process_packages(); + + + + + + +// Get least difference + int64_t min_difference = -1; +#ifdef STDDEV_TEST + double stddev_table[get_total_packages()]; +#endif + for(int i = 0; i < get_total_packages(); i++) + { + MotionHVScanPackage *pkg = (MotionHVScanPackage*)get_package(i); + +#ifdef STDDEV_TEST + double stddev = sqrt(pkg->difference1) / + (block_w / current_downsample) / + (block_h / current_downsample) / + 3; +// printf("MotionHVScan::pixel_search %d current_downsample=%d search_x=%d search_y=%d diff1=%f\n", +// __LINE__, +// current_downsample, +// pkg->search_x, +// pkg->search_y, +// sqrt(pkg->difference1) / block_w / current_downsample / block_h / 3 /* / variance */); + +// printf("MotionHVScan::pixel_search %d range1=%f stddev=%f\n", +// __LINE__, +// range1, +// stddev); + + stddev_table[i] = stddev; +#endif // STDDEV_TEST + + if(pkg->difference1 < min_difference || i == 0) + { + min_difference = pkg->difference1; + x_result = pkg->search_x * current_downsample * OVERSAMPLE; + y_result = pkg->search_y * current_downsample * OVERSAMPLE; + +// printf("MotionHVScan::pixel_search %d x_result=%d y_result=%d angle_step=%d diff=%lld\n", +// __LINE__, +// block_x1 * OVERSAMPLE - x_result, +// block_y1 * OVERSAMPLE - y_result, +// pkg->angle_step, +// pkg->difference1); + + } + } + + +#ifdef STDDEV_TEST + qsort(stddev_table, get_total_packages(), sizeof(double), compare); + + +// reject motion vector if not similar enough +// if(stddev_table[0] > 0.2) +// { +// if(debug) +// { +// printf("MotionHVScan::pixel_search %d stddev fail min_stddev=%f\n", +// __LINE__, +// stddev_table[0]); +// } +// failed = 1; +// return; +// } + +if(debug) +{ + printf("MotionHVScan::pixel_search %d\n", __LINE__); + for(int i = 0; i < get_total_packages(); i++) + { + printf("%f\n", stddev_table[i]); + } +} + +// reject motion vector if not a sigmoid curve +// TODO: use linear interpolation + int steps = 2; + int step = get_total_packages() / steps; + double curve[steps]; + for(int i = 0; i < steps; i++) + { + int start = get_total_packages() * i / steps; + int end = get_total_packages() * (i + 1) / steps; + end = MIN(end, get_total_packages() - 1); + curve[i] = stddev_table[end] - stddev_table[start]; + } + + +// if(curve[0] < (curve[1] * 1.01) || +// curve[2] < (curve[1] * 1.01) || +// curve[0] < (curve[2] * 0.75)) +// if(curve[0] < curve[1]) +// { +// if(debug) +// { +// printf("MotionHVScan::pixel_search %d curve fail %f %f\n", +// __LINE__, +// curve[0], +// curve[1]); +// } +// failed = 1; +// return; +// } + +if(debug) +{ +printf("MotionHVScan::pixel_search %d curve=%f %f ranges=%f %f min_stddev=%f\n", +__LINE__, +curve[0], +curve[1], +range1, +range2, +stddev_table[0]); +} +#endif // STDDEV_TEST + + + + + + if(do_rotate) + { + rotation_pass = 1;; + total_steps = angle_steps; + scan_x1 = x_result / OVERSAMPLE; + scan_y1 = y_result / OVERSAMPLE; + set_package_count(total_steps); + process_packages(); + + + + min_difference = -1; + double prev_r_result = r_result; + for(int i = 0; i < get_total_packages(); i++) + { + MotionHVScanPackage *pkg = (MotionHVScanPackage*)get_package(i); + +// printf("MotionHVScan::pixel_search %d search_x=%d search_y=%d angle_step=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", +// __LINE__, +// pkg->search_x, +// pkg->search_y, +// pkg->search_angle_step, +// pkg->sub_x, +// pkg->sub_y, +// pkg->difference1, +// pkg->difference2); + if(pkg->difference1 < min_difference || i == 0) + { + min_difference = pkg->difference1; + r_result = step_to_angle(i, prev_r_result); + + // printf("MotionHVScan::pixel_search %d x_result=%d y_result=%d angle_step=%d diff=%lld\n", + // __LINE__, + // block_x1 * OVERSAMPLE - x_result, + // block_y1 * OVERSAMPLE - y_result, + // pkg->angle_step, + // pkg->difference1); + } + } + } + + +// printf("MotionHVScan::scan_frame %d current_downsample=%d x_result=%f y_result=%f r_result=%f\n", +// __LINE__, +// current_downsample, +// (float)x_result / OVERSAMPLE, +// (float)y_result / OVERSAMPLE, +// r_result); + +} + + +// subpixel motion search +void MotionHVScan::subpixel_search(int &x_result, int &y_result) +{ + rotation_pass = 0; + previous_frame = previous_frame_arg; + current_frame = current_frame_arg; + +//printf("MotionHVScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result); +// Scan every subpixel in a SUBPIXEL_RANGE * SUBPIXEL_RANGE square + total_steps = (SUBPIXEL_RANGE * OVERSAMPLE) * (SUBPIXEL_RANGE * OVERSAMPLE); + +// These aren't used in subpixel + x_steps = OVERSAMPLE * SUBPIXEL_RANGE; + y_steps = OVERSAMPLE * SUBPIXEL_RANGE; + angle_steps = 1; + + set_package_count(this->total_steps); + process_packages(); + +// Get least difference + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + MotionHVScanPackage *pkg = (MotionHVScanPackage*)get_package(i); +//printf("MotionHVScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", +//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2); + if(pkg->difference1 < min_difference || min_difference == -1) + { + min_difference = pkg->difference1; + +// The sub coords are 1 pixel up & left of the block coords + x_result = pkg->search_x * OVERSAMPLE + pkg->sub_x; + y_result = pkg->search_y * OVERSAMPLE + pkg->sub_y; + + +// Fill in results + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; +//printf("MotionHVScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", +//__LINE__, dx_result, dy_result, min_difference); + } + + if(pkg->difference2 < min_difference) + { + min_difference = pkg->difference2; + + x_result = pkg->search_x * OVERSAMPLE - pkg->sub_x; + y_result = pkg->search_y * OVERSAMPLE - pkg->sub_y; + + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; +//printf("MotionHVScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", +//__LINE__, dx_result, dy_result, min_difference); + } + } +} + + +void MotionHVScan::scan_frame(VFrame *previous_frame, + VFrame *current_frame, + int global_range_w, + int global_range_h, + int global_block_w, + int global_block_h, + int block_x, + int block_y, + int frame_type, + int tracking_type, + int action_type, + int horizontal_only, + int vertical_only, + int source_position, + int total_dx, + int total_dy, + int global_origin_x, + int global_origin_y, + int do_motion, + int do_rotate, + double rotation_center, + double rotation_range) +{ + this->previous_frame_arg = previous_frame; + this->current_frame_arg = current_frame; + this->horizontal_only = horizontal_only; + this->vertical_only = vertical_only; + this->previous_frame = previous_frame_arg; + this->current_frame = current_frame_arg; + this->global_origin_x = global_origin_x; + this->global_origin_y = global_origin_y; + this->action_type = action_type; + this->do_motion = do_motion; + this->do_rotate = do_rotate; + this->rotation_center = rotation_center; + this->rotation_range = rotation_range; + +//printf("MotionHVScan::scan_frame %d\n", __LINE__); + dx_result = 0; + dy_result = 0; + dr_result = 0; + failed = 0; + + subpixel = 0; +// starting level of detail +// TODO: base it on a table of resolutions + current_downsample = STARTING_DOWNSAMPLE; + angle_step = 0; + +// Single macroblock + int w = current_frame->get_w(); + int h = current_frame->get_h(); + +// Initial search parameters + scan_w = global_range_w; + scan_h = global_range_h; + + int block_w = global_block_w; + int block_h = global_block_h; + +// printf("MotionHVScan::scan_frame %d %d %d %d %d %d %d %d %d\n", +// __LINE__, +// global_range_w, +// global_range_h, +// global_block_w, +// global_block_h, +// scan_w, +// scan_h, +// block_w, +// block_h); + +// Location of block in previous frame + block_x1 = (int)(block_x - block_w / 2); + block_y1 = (int)(block_y - block_h / 2); + block_x2 = (int)(block_x + block_w / 2); + block_y2 = (int)(block_y + block_h / 2); + +// Offset to location of previous block. This offset needn't be very accurate +// since it's the offset of the previous image and current image we want. + if(frame_type == MotionHVScan::TRACK_PREVIOUS) + { + block_x1 += total_dx / OVERSAMPLE; + block_y1 += total_dy / OVERSAMPLE; + block_x2 += total_dx / OVERSAMPLE; + block_y2 += total_dy / OVERSAMPLE; + } + + skip = 0; + + switch(tracking_type) + { +// Don't calculate + case MotionHVScan::NO_CALCULATE: + dx_result = 0; + dy_result = 0; + dr_result = rotation_center; + skip = 1; + break; + + case MotionHVScan::LOAD: + { +// Load result from disk + char string[BCTEXTLEN]; + + skip = 1; + if(do_motion) + { + sprintf(string, "%s%06d", + MOTION_FILE, + source_position); +//printf("MotionHVScan::scan_frame %d %s\n", __LINE__, string); + FILE *input = fopen(string, "r"); + if(input) + { + int temp = fscanf(input, + "%d %d", + &dx_result, + &dy_result); + if( temp != 2 ) + printf("MotionHVScan::scan_frame %d %s\n", __LINE__, string); +// HACK +//dx_result *= 2; +//dy_result *= 2; +//printf("MotionHVScan::scan_frame %d %d %d\n", __LINE__, dx_result, dy_result); + fclose(input); + } + else + { + skip = 0; + } + } + + if(do_rotate) + { + sprintf(string, + "%s%06d", + ROTATION_FILE, + source_position); + FILE *input = fopen(string, "r"); + if(input) + { + int temp = fscanf(input, "%f", &dr_result); + if( temp != 1 ) + printf("MotionHVScan::scan_frame %d %s\n", __LINE__, string); +// DEBUG +//dr_result += 0.25; + fclose(input); + } + else + { + skip = 0; + } + } + break; + } + +// Scan from scratch + default: + skip = 0; + break; + } + + + + if(!skip && test_match) + { + if(previous_frame->data_matches(current_frame)) + { +printf("MotionHVScan::scan_frame: data matches. skipping.\n"); + dx_result = 0; + dy_result = 0; + dr_result = rotation_center; + skip = 1; + } + } + + +// Perform scan + if(!skip) + { +// Location of block in current frame + int origin_offset_x = this->global_origin_x; + int origin_offset_y = this->global_origin_y; + int x_result = block_x1 + origin_offset_x; + int y_result = block_y1 + origin_offset_y; + double r_result = rotation_center; + +// printf("MotionHVScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", +// block_x1 + block_w / 2, +// block_y1 + block_h / 2, +// block_w, +// block_h, +// block_x1, +// block_y1, +// block_x2, +// block_y2); + + while(!failed) + { + scan_x1 = x_result - scan_w / 2; + scan_y1 = y_result - scan_h / 2; + scan_x2 = x_result + scan_w / 2; + scan_y2 = y_result + scan_h / 2; + scan_angle1 = r_result - rotation_range; + scan_angle2 = r_result + rotation_range; + + + +// Zero out requested values +// if(horizontal_only) +// { +// scan_y1 = block_y1; +// scan_y2 = block_y1 + 1; +// } +// if(vertical_only) +// { +// scan_x1 = block_x1; +// scan_x2 = block_x1 + 1; +// } + +// printf("MotionHVScan::scan_frame %d block_x1=%d block_y1=%d block_x2=%d block_y2=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d\n", +// __LINE__, +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2); + + +// Clamp the block coords before the scan so we get useful scan coords. + clamp_scan(w, + h, + &block_x1, + &block_y1, + &block_x2, + &block_y2, + &scan_x1, + &scan_y1, + &scan_x2, + &scan_y2, + 0); + + +// printf("MotionHVScan::scan_frame %d block_x1=%d block_y1=%d block_x2=%d block_y2=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d x_result=%d y_result=%d\n", +// __LINE__, +// block_x1, +// block_y1, +// block_x2, +// block_y2, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2, +// x_result, +// y_result); +//if(y_result == 88) exit(0); + + +// Give up if invalid coords. + if(scan_y2 <= scan_y1 || + scan_x2 <= scan_x1 || + block_x2 <= block_x1 || + block_y2 <= block_y1) + { + break; + } + +// For subpixel, the top row and left column are skipped + if(subpixel) + { + + subpixel_search(x_result, y_result); +// printf("MotionHVScan::scan_frame %d x_result=%d y_result=%d\n", +// __LINE__, +// x_result / OVERSAMPLE, +// y_result / OVERSAMPLE); + + break; + } + else +// Single pixel + { + pixel_search(x_result, y_result, r_result); +//printf("MotionHVScan::scan_frame %d x_result=%d y_result=%d\n", __LINE__, x_result / OVERSAMPLE, y_result / OVERSAMPLE); + + if(failed) + { + dr_result = 0; + dx_result = 0; + dy_result = 0; + } + else + if(current_downsample <= 1) + { + // Single pixel accuracy reached. Now do exhaustive subpixel search. + if(action_type == MotionHVScan::STABILIZE || + action_type == MotionHVScan::TRACK || + action_type == MotionHVScan::NOTHING) + { + x_result /= OVERSAMPLE; + y_result /= OVERSAMPLE; +//printf("MotionHVScan::scan_frame %d x_result=%d y_result=%d\n", __LINE__, x_result, y_result); + scan_w = SUBPIXEL_RANGE; + scan_h = SUBPIXEL_RANGE; +// Final R result + dr_result = rotation_center - r_result; + subpixel = 1; + } + else + { +// Fill in results and quit + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; + dr_result = rotation_center - r_result; + break; + } + } + else +// Reduce scan area and try again + { +// scan_w = (scan_x2 - scan_x1) / 2; +// scan_h = (scan_y2 - scan_y1) / 2; +// need slightly more than 2x downsampling factor + + if(current_downsample * 3 < scan_w && + current_downsample * 3 < scan_h) + { + scan_w = current_downsample * 3; + scan_h = current_downsample * 3; + } + + if(angle_step * 1.5 < rotation_range) + { + rotation_range = angle_step * 1.5; + } +//printf("MotionHVScan::scan_frame %d %f %f\n", __LINE__, angle_step, rotation_range); + + current_downsample /= 2; + +// convert back to pixels + x_result /= OVERSAMPLE; + y_result /= OVERSAMPLE; +// debug +//exit(1); + } + + } + } + + dx_result *= -1; + dy_result *= -1; + dr_result *= -1; + } +// printf("MotionHVScan::scan_frame %d dx=%f dy=%f dr=%f\n", +// __LINE__, +// (float)dx_result / OVERSAMPLE, +// (float)dy_result / OVERSAMPLE, +// dr_result); + + + + +// Write results + if(!skip && tracking_type == MotionHVScan::SAVE) + { + char string[BCTEXTLEN]; + + + if(do_motion) + { + sprintf(string, + "%s%06d", + MOTION_FILE, + source_position); + FILE *output = fopen(string, "w"); + if(output) + { + fprintf(output, + "%d %d\n", + dx_result, + dy_result); + fclose(output); + } + else + { + printf("MotionHVScan::scan_frame %d: save motion failed\n", __LINE__); + } + } + + if(do_rotate) + { + sprintf(string, + "%s%06d", + ROTATION_FILE, + source_position); + FILE *output = fopen(string, "w"); + if(output) + { + fprintf(output, "%f\n", dr_result); + fclose(output); + } + else + { + printf("MotionHVScan::scan_frame %d save rotation failed\n", __LINE__); + } + } + } + + + if(vertical_only) dx_result = 0; + if(horizontal_only) dy_result = 0; + +// printf("MotionHVScan::scan_frame %d dx=%d dy=%d\n", +// __LINE__, +// this->dx_result, +// this->dy_result); +} + + + + + + + + + + + + + + + + + + + +#define ABS_DIFF(type, temp_type, multiplier, components) \ +{ \ + temp_type result_temp = 0; \ + for(int i = 0; i < h; i++) \ + { \ + type *prev_row = (type*)prev_ptr; \ + type *current_row = (type*)current_ptr; \ + for(int j = 0; j < w; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + temp_type difference; \ + difference = *prev_row++ - *current_row++; \ + difference *= difference; \ + result_temp += difference; \ + } \ + if(components == 4) \ + { \ + prev_row++; \ + current_row++; \ + } \ + } \ + prev_ptr += row_bytes; \ + current_ptr += row_bytes; \ + } \ + result = (int64_t)(result_temp * multiplier); \ +} + +int64_t MotionHVScan::abs_diff(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model) +{ + int64_t result = 0; + switch(color_model) + { + case BC_RGB888: + ABS_DIFF(unsigned char, int64_t, 1, 3) + break; + case BC_RGBA8888: + ABS_DIFF(unsigned char, int64_t, 1, 4) + break; + case BC_RGB_FLOAT: + ABS_DIFF(float, double, 0x10000, 3) + break; + case BC_RGBA_FLOAT: + ABS_DIFF(float, double, 0x10000, 4) + break; + case BC_YUV888: + ABS_DIFF(unsigned char, int64_t, 1, 3) + break; + case BC_YUVA8888: + ABS_DIFF(unsigned char, int64_t, 1, 4) + break; + } + return result; +} + + + +#define ABS_DIFF_SUB(type, temp_type, multiplier, components) \ +{ \ + temp_type result_temp = 0; \ + temp_type y2_fraction = sub_y * 0x100 / OVERSAMPLE; \ + temp_type y1_fraction = 0x100 - y2_fraction; \ + temp_type x2_fraction = sub_x * 0x100 / OVERSAMPLE; \ + temp_type x1_fraction = 0x100 - x2_fraction; \ + for(int i = 0; i < h_sub; i++) \ + { \ + type *prev_row1 = (type*)prev_ptr; \ + type *prev_row2 = (type*)prev_ptr + components; \ + type *prev_row3 = (type*)(prev_ptr + row_bytes); \ + type *prev_row4 = (type*)(prev_ptr + row_bytes) + components; \ + type *current_row = (type*)current_ptr; \ + for(int j = 0; j < w_sub; j++) \ + { \ +/* Scan each component */ \ + for(int k = 0; k < 3; k++) \ + { \ + temp_type difference; \ + temp_type prev_value = \ + (*prev_row1++ * x1_fraction * y1_fraction + \ + *prev_row2++ * x2_fraction * y1_fraction + \ + *prev_row3++ * x1_fraction * y2_fraction + \ + *prev_row4++ * x2_fraction * y2_fraction) / \ + 0x100 / 0x100; \ + temp_type current_value = *current_row++; \ + difference = prev_value - current_value; \ + difference *= difference; \ + result_temp += difference; \ + } \ + \ +/* skip alpha */ \ + if(components == 4) \ + { \ + prev_row1++; \ + prev_row2++; \ + prev_row3++; \ + prev_row4++; \ + current_row++; \ + } \ + } \ + prev_ptr += row_bytes; \ + current_ptr += row_bytes; \ + } \ + result = (int64_t)(result_temp * multiplier); \ +} + + + + +int64_t MotionHVScan::abs_diff_sub(unsigned char *prev_ptr, + unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model, + int sub_x, + int sub_y) +{ + int h_sub = h - 1; + int w_sub = w - 1; + int64_t result = 0; + + switch(color_model) + { + case BC_RGB888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) + break; + case BC_RGBA8888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) + break; + case BC_RGB_FLOAT: + ABS_DIFF_SUB(float, double, 0x10000, 3) + break; + case BC_RGBA_FLOAT: + ABS_DIFF_SUB(float, double, 0x10000, 4) + break; + case BC_YUV888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) + break; + case BC_YUVA8888: + ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) + break; + } + return result; +} + + +#if 0 +#define VARIANCE(type, temp_type, multiplier, components) \ +{ \ + temp_type average[3] = { 0 }; \ + temp_type variance[3] = { 0 }; \ + \ + for(int i = 0; i < h; i++) \ + { \ + type *row = (type*)current_ptr + i * row_bytes; \ + for(int j = 0; j < w; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + average[k] += row[k]; \ + } \ + row += components; \ + } \ + } \ + for(int k = 0; k < 3; k++) \ + { \ + average[k] /= w * h; \ + } \ + \ + for(int i = 0; i < h; i++) \ + { \ + type *row = (type*)current_ptr + i * row_bytes; \ + for(int j = 0; j < w; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + variance[k] += SQR(row[k] - average[k]); \ + } \ + row += components; \ + } \ + } \ + result = (double)multiplier * \ + sqrt((variance[0] + variance[1] + variance[2]) / w / h / 3); \ +} + +double MotionHVScan::calculate_variance(unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model) +{ + double result = 0; + + switch(color_model) + { + case BC_RGB888: + VARIANCE(unsigned char, int, 1, 3) + break; + case BC_RGBA8888: + VARIANCE(unsigned char, int, 1, 4) + break; + case BC_RGB_FLOAT: + VARIANCE(float, double, 255, 3) + break; + case BC_RGBA_FLOAT: + VARIANCE(float, double, 255, 4) + break; + case BC_YUV888: + VARIANCE(unsigned char, int, 1, 3) + break; + case BC_YUVA8888: + VARIANCE(unsigned char, int, 1, 4) + break; + } + + + return result; +} +#endif // 0 + + + + +#define RANGE(type, temp_type, multiplier, components) \ +{ \ + temp_type min[3]; \ + temp_type max[3]; \ + min[0] = 0x7fff; \ + min[1] = 0x7fff; \ + min[2] = 0x7fff; \ + max[0] = 0; \ + max[1] = 0; \ + max[2] = 0; \ + \ + for(int i = 0; i < h; i++) \ + { \ + type *row = (type*)current_ptr + i * row_bytes; \ + for(int j = 0; j < w; j++) \ + { \ + for(int k = 0; k < 3; k++) \ + { \ + if(row[k] > max[k]) max[k] = row[k]; \ + if(row[k] < min[k]) min[k] = row[k]; \ + } \ + row += components; \ + } \ + } \ + \ + for(int k = 0; k < 3; k++) \ + { \ + /* printf("MotionHVScan::calculate_range %d k=%d max=%d min=%d\n", __LINE__, k, max[k], min[k]); */ \ + if(max[k] - min[k] > result) result = max[k] - min[k]; \ + } \ + \ +} + +double MotionHVScan::calculate_range(unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model) +{ + double result = 0; + + switch(color_model) + { + case BC_RGB888: + RANGE(unsigned char, int, 1, 3) + break; + case BC_RGBA8888: + RANGE(unsigned char, int, 1, 4) + break; + case BC_RGB_FLOAT: + RANGE(float, float, 255, 3) + break; + case BC_RGBA_FLOAT: + RANGE(float, float, 255, 4) + break; + case BC_YUV888: + RANGE(unsigned char, int, 1, 3) + break; + case BC_YUVA8888: + RANGE(unsigned char, int, 1, 4) + break; + } + + + return result; +} + + +//#define CLAMP_BLOCK + +// this truncates the scan area but not the macroblock unless the macro is defined +void MotionHVScan::clamp_scan(int w, + int h, + int *block_x1, + int *block_y1, + int *block_x2, + int *block_y2, + int *scan_x1, + int *scan_y1, + int *scan_x2, + int *scan_y2, + int use_absolute) +{ +// printf("MotionHVMain::clamp_scan 1 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", +// w, +// h, +// *block_x1, +// *block_y1, +// *block_x2, +// *block_y2, +// *scan_x1, +// *scan_y1, +// *scan_x2, +// *scan_y2, +// use_absolute); + + if(use_absolute) + { +// Limit size of scan area +// Used for drawing vectors +// scan is always out of range before block. + if(*scan_x1 < 0) + { +#ifdef CLAMP_BLOCK + int difference = -*scan_x1; + *block_x1 += difference; +#endif + *scan_x1 = 0; + } + + if(*scan_y1 < 0) + { +#ifdef CLAMP_BLOCK + int difference = -*scan_y1; + *block_y1 += difference; +#endif + *scan_y1 = 0; + } + + if(*scan_x2 > w) + { + int difference = *scan_x2 - w; +#ifdef CLAMP_BLOCK + *block_x2 -= difference; +#endif + *scan_x2 -= difference; + } + + if(*scan_y2 > h) + { + int difference = *scan_y2 - h; +#ifdef CLAMP_BLOCK + *block_y2 -= difference; +#endif + *scan_y2 -= difference; + } + + CLAMP(*scan_x1, 0, w); + CLAMP(*scan_y1, 0, h); + CLAMP(*scan_x2, 0, w); + CLAMP(*scan_y2, 0, h); + } + else + { +// Limit range of upper left block coordinates +// Used for motion tracking + if(*scan_x1 < 0) + { + int difference = -*scan_x1; +#ifdef CLAMP_BLOCK + *block_x1 += difference; +#endif + *scan_x2 += difference; + *scan_x1 = 0; + } + + if(*scan_y1 < 0) + { + int difference = -*scan_y1; +#ifdef CLAMP_BLOCK + *block_y1 += difference; +#endif + *scan_y2 += difference; + *scan_y1 = 0; + } + + if(*scan_x2 - *block_x1 + *block_x2 > w) + { + int difference = *scan_x2 - *block_x1 + *block_x2 - w; + *scan_x2 -= difference; +#ifdef CLAMP_BLOCK + *block_x2 -= difference; +#endif + } + + if(*scan_y2 - *block_y1 + *block_y2 > h) + { + int difference = *scan_y2 - *block_y1 + *block_y2 - h; + *scan_y2 -= difference; +#ifdef CLAMP_BLOCK + *block_y2 -= difference; +#endif + } + +// CLAMP(*scan_x1, 0, w - (*block_x2 - *block_x1)); +// CLAMP(*scan_y1, 0, h - (*block_y2 - *block_y1)); +// CLAMP(*scan_x2, 0, w - (*block_x2 - *block_x1)); +// CLAMP(*scan_y2, 0, h - (*block_y2 - *block_y1)); + } + +// Sanity checks which break the calculation but should never happen if the +// center of the block is inside the frame. + CLAMP(*block_x1, 0, w); + CLAMP(*block_x2, 0, w); + CLAMP(*block_y1, 0, h); + CLAMP(*block_y2, 0, h); + +// printf("MotionHVMain::clamp_scan 2 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", +// w, +// h, +// *block_x1, +// *block_y1, +// *block_x2, +// *block_y2, +// *scan_x1, +// *scan_y1, +// *scan_x2, +// *scan_y2, +// use_absolute); +} + + + diff --git a/cinelerra-5.1/plugins/motion.new/motionscan.h b/cinelerra-5.1/plugins/motion-hv/motionscan-hv.h similarity index 62% rename from cinelerra-5.1/plugins/motion.new/motionscan.h rename to cinelerra-5.1/plugins/motion-hv/motionscan-hv.h index 7bee1222..7511e642 100644 --- a/cinelerra-5.1/plugins/motion.new/motionscan.h +++ b/cinelerra-5.1/plugins/motion-hv/motionscan-hv.h @@ -1,7 +1,7 @@ /* * CINELERRA - * Copyright (C) 2008 Adam Williams + * Copyright (C) 2016 Adam Williams * * 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 @@ -23,27 +23,28 @@ #define MOTIONSCAN_H -#include "arraylist.h" -//#include "../downsample/downsampleengine.inc" +#include "affine.inc" #include "loadbalance.h" #include "vframe.inc" #include -class MotionScan; +class MotionHVScan; #define OVERSAMPLE 4 -#define MOTION_FILE "/tmp/motion" +#define MOTION_FILE "/tmp/m" +#define ROTATION_FILE "/tmp/r" -class MotionScanPackage : public LoadPackage +class MotionHVScanPackage : public LoadPackage { public: - MotionScanPackage(); + MotionHVScanPackage(); // For multiple blocks -// Position of stationary block +// Position of stationary block after downsampling int block_x1, block_y1, block_x2, block_y2; -// Range of positions to scan - int scan_x1, scan_y1, scan_x2, scan_y2; +// index of rotated frame + int angle_step; + int dx; int dy; int64_t max_difference; @@ -51,11 +52,9 @@ public: int64_t min_pixel; int is_border; int valid; -// For single block - int step; int64_t difference1; int64_t difference2; -// Search position to nearest pixel +// Search position of current package to nearest pixel with downsampling int search_x; int search_y; // Subpixel of search position @@ -63,38 +62,27 @@ public: int sub_y; }; -class MotionScanCache +class MotionHVScanUnit : public LoadClient { public: - MotionScanCache(int x, int y, int64_t difference); - int x, y; - int64_t difference; -}; - -class MotionScanUnit : public LoadClient -{ -public: - MotionScanUnit(MotionScan *server); - ~MotionScanUnit(); + MotionHVScanUnit(MotionHVScan *server); + ~MotionHVScanUnit(); void process_package(LoadPackage *package); - int64_t get_cache(int x, int y); - void put_cache(int x, int y, int64_t difference); - - MotionScan *server; + void subpixel(MotionHVScanPackage *pkg); + void single_pixel(MotionHVScanPackage *pkg); - ArrayList cache; - Mutex *cache_lock; + MotionHVScan *server; }; -class MotionScan : public LoadServer +class MotionHVScan : public LoadServer { public: - MotionScan(int total_clients, + MotionHVScan(int total_clients, int total_packages); - ~MotionScan(); + ~MotionHVScan(); - friend class MotionScanUnit; + friend class MotionHVScanUnit; void init_packages(); LoadClient* new_client(); @@ -105,27 +93,27 @@ public: // Invoke the motion engine for a search // Frame before motion void scan_frame(VFrame *previous_frame, -// Frame after motion VFrame *current_frame, - int global_range_w, + int global_range_w, // in pixels int global_range_h, - int global_block_w, + int global_block_w, // in pixels int global_block_h, - double block_x, - double block_y, + int block_x, // in pixels + int block_y, int frame_type, int tracking_type, int action_type, int horizontal_only, int vertical_only, int source_position, - int total_steps, - int total_dx, + int total_dx, // in pixels * OVERSAMPLE int total_dy, - int global_origin_x, - int global_origin_y); - int64_t get_cache(int x, int y); - void put_cache(int x, int y, int64_t difference); + int global_origin_x, // in pixels + int global_origin_y, + int do_motion, + int do_rotate, + double rotation_center, // in deg + double rotation_range); static int64_t abs_diff(unsigned char *prev_ptr, unsigned char *current_ptr, @@ -159,6 +147,7 @@ public: // OVERSAMPLE int dx_result; int dy_result; + float dr_result; enum { @@ -188,6 +177,27 @@ public: }; private: + void downsample_frame(VFrame *dst, + VFrame *src, + int downsample); + void pixel_search(int &x_result, int &y_result, double &r_result); + void subpixel_search(int &x_result, int &y_result); + double step_to_angle(int step, double center); + +// double calculate_variance(unsigned char *current_ptr, +// int row_bytes, +// int w, +// int h, +// int color_model); + double calculate_range(unsigned char *current_ptr, + int row_bytes, + int w, + int h, + int color_model); + + + + AffineEngine *rotater; // Pointer to downsampled frame before motion VFrame *previous_frame; // Pointer to downsampled frame after motion @@ -198,33 +208,49 @@ private: // Downsampled frames VFrame *downsampled_previous; VFrame *downsampled_current; +// rotated versions of current_frame + VFrame **rotated_current; +// allocation of rotated_current array, a copy of angle_steps + int total_rotated; // Test for identical frames before processing // Faster to skip it if the frames are usually different int test_match; int skip; +// macroblocks didn't have enough data + int failed; // For single block int block_x1; int block_x2; int block_y1; int block_y2; + int scan_w; + int scan_h; int scan_x1; int scan_y1; int scan_x2; int scan_y2; - int total_pixels; - int total_steps; - int edge_steps; + double scan_angle1, scan_angle2; int y_steps; int x_steps; + int angle_steps; +// in deg + double angle_step; int subpixel; int horizontal_only; int vertical_only; int global_origin_x; int global_origin_y; - - ArrayList cache; - Mutex *cache_lock; -// DownSampleServer *downsample; + int action_type; + int current_downsample; + int downsampled_w; + int downsampled_h; + int total_steps; + int do_motion; + int do_rotate; + int rotation_pass; +// in deg + double rotation_center; + double rotation_range; }; diff --git a/cinelerra-5.1/plugins/motion.new/motionscan.inc b/cinelerra-5.1/plugins/motion-hv/motionscan-hv.inc similarity index 92% rename from cinelerra-5.1/plugins/motion.new/motionscan.inc rename to cinelerra-5.1/plugins/motion-hv/motionscan-hv.inc index 4e8229ed..dd2e376b 100644 --- a/cinelerra-5.1/plugins/motion.new/motionscan.inc +++ b/cinelerra-5.1/plugins/motion-hv/motionscan-hv.inc @@ -19,13 +19,13 @@ * */ -#ifndef MOTIONSCAN_INC -#define MOTIONSCAN_INC +#ifndef MOTIONSCANHV_INC +#define MOTIONSCANHV_INC -class MotionScan; +class MotionHVScan; diff --git a/cinelerra-5.1/plugins/motion.new/motionwindow.C b/cinelerra-5.1/plugins/motion-hv/motionwindow-hv.C similarity index 60% rename from cinelerra-5.1/plugins/motion.new/motionwindow.C rename to cinelerra-5.1/plugins/motion-hv/motionwindow-hv.C index 26d7075a..ad536ba5 100644 --- a/cinelerra-5.1/plugins/motion.new/motionwindow.C +++ b/cinelerra-5.1/plugins/motion-hv/motionwindow-hv.C @@ -1,7 +1,7 @@ /* * CINELERRA - * Copyright (C) 2008 Adam Williams + * Copyright (C) 2012 Adam Williams * * 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 @@ -22,9 +22,9 @@ #include "bcdisplayinfo.h" #include "clip.h" #include "language.h" -#include "motion.h" -#include "motionscan.h" -#include "motionwindow.h" +#include "motion-hv.h" +#include "motionscan-hv.h" +#include "motionwindow-hv.h" @@ -35,22 +35,17 @@ -MotionWindow::MotionWindow(MotionMain *plugin) - : PluginClientWindow(plugin, - 600, - 650, - 600, - 650, - 0) +MotionHVWindow::MotionHVWindow(MotionHVMain *plugin) + : PluginClientWindow(plugin, 600, 650, 600, 650, 0) { this->plugin = plugin; } -MotionWindow::~MotionWindow() +MotionHVWindow::~MotionHVWindow() { } -void MotionWindow::create_objects() +void MotionHVWindow::create_objects() { int x1 = 10, x = 10, y = 10; int x2 = 310; @@ -58,12 +53,12 @@ void MotionWindow::create_objects() - add_subwindow(global = new MotionGlobal(plugin, - this, - x1, - y)); +// add_subwindow(global = new MotionHVGlobal(plugin, +// this, +// x1, +// y)); - add_subwindow(rotate = new MotionRotate(plugin, + add_subwindow(rotate = new MotionHVRotate(plugin, this, x2, y)); @@ -101,32 +96,32 @@ void MotionWindow::create_objects() y, &plugin->config.global_block_h)); - add_subwindow(title = new BC_Title(x2, - y, - _("Rotation block size:\n(W/H Percent of image)"))); - add_subwindow(rotation_block_w = new BlockSize(plugin, - x2 + title->get_w() + 10, - y, - &plugin->config.rotation_block_w)); - add_subwindow(rotation_block_h = new BlockSize(plugin, - x2 + title->get_w() + 10 + rotation_block_w->get_w(), - y, - &plugin->config.rotation_block_h)); - - y += 50; - add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:"))); - add_subwindow(global_search_positions = new GlobalSearchPositions(plugin, - x1 + title->get_w() + 10, - y, - 80)); - global_search_positions->create_objects(); - - add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:"))); - add_subwindow(rotation_search_positions = new RotationSearchPositions(plugin, - x2 + title->get_w() + 10, - y, - 80)); - rotation_search_positions->create_objects(); +// add_subwindow(title = new BC_Title(x2, +// y, +// _("Rotation block size:\n(W/H Percent of image)"))); +// add_subwindow(rotation_block_w = new BlockSize(plugin, +// x2 + title->get_w() + 10, +// y, +// &plugin->config.rotation_block_w)); +// add_subwindow(rotation_block_h = new BlockSize(plugin, +// x2 + title->get_w() + 10 + rotation_block_w->get_w(), +// y, +// &plugin->config.rotation_block_h)); + +// y += 50; +// add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:"))); +// add_subwindow(global_search_positions = new GlobalSearchPositions(plugin, +// x1 + title->get_w() + 10, +// y, +// 80)); +// global_search_positions->create_objects(); +// +// add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:"))); +// add_subwindow(rotation_search_positions = new RotationSearchPositions(plugin, +// x2 + title->get_w() + 10, +// y, +// 80)); +// rotation_search_positions->create_objects(); y += 50; add_subwindow(title = new BC_Title(x, y, _("Translation direction:"))); @@ -138,11 +133,11 @@ void MotionWindow::create_objects() y += 40; add_subwindow(title = new BC_Title(x, y + 10, _("Block X:"))); - add_subwindow(block_x = new MotionBlockX(plugin, + add_subwindow(block_x = new MotionHVBlockX(plugin, this, x + title->get_w() + 10, y)); - add_subwindow(block_x_text = new MotionBlockXText(plugin, + add_subwindow(block_x_text = new MotionHVBlockXText(plugin, this, x + title->get_w() + 10 + block_x->get_w() + 10, y + 10)); @@ -157,46 +152,46 @@ void MotionWindow::create_objects() int y1 = y; y += 50; add_subwindow(title = new BC_Title(x2, y + 10, _("Maximum angle offset:"))); - add_subwindow(rotate_magnitude = new MotionRMagnitude(plugin, + add_subwindow(rotate_magnitude = new MotionHVRMagnitude(plugin, x2 + title->get_w() + 10, y)); y += 40; add_subwindow(title = new BC_Title(x2, y + 10, _("Rotation settling speed:"))); - add_subwindow(rotate_return_speed = new MotionRReturnSpeed(plugin, + add_subwindow(rotate_return_speed = new MotionHVRReturnSpeed(plugin, x2 + title->get_w() + 10, y)); - + y = y1; y += 40; add_subwindow(title = new BC_Title(x, y + 10, _("Block Y:"))); - add_subwindow(block_y = new MotionBlockY(plugin, + add_subwindow(block_y = new MotionHVBlockY(plugin, this, x + title->get_w() + 10, y)); - add_subwindow(block_y_text = new MotionBlockYText(plugin, + add_subwindow(block_y_text = new MotionHVBlockYText(plugin, this, x + title->get_w() + 10 + block_y->get_w() + 10, y + 10)); y += 50; add_subwindow(title = new BC_Title(x, y + 10, _("Maximum absolute offset:"))); - add_subwindow(magnitude = new MotionMagnitude(plugin, + add_subwindow(magnitude = new MotionHVMagnitude(plugin, x + title->get_w() + 10, y)); y += 40; - add_subwindow(title = new BC_Title(x, y + 10, _("Settling speed:"))); - add_subwindow(return_speed = new MotionReturnSpeed(plugin, + add_subwindow(title = new BC_Title(x, y + 10, _("MotionHV settling speed:"))); + add_subwindow(return_speed = new MotionHVReturnSpeed(plugin, x + title->get_w() + 10, y)); y += 40; - add_subwindow(vectors = new MotionDrawVectors(plugin, + add_subwindow(vectors = new MotionHVDrawVectors(plugin, this, x, y)); @@ -258,11 +253,10 @@ void MotionWindow::create_objects() - show_window(); - flush(); + show_window(1); } -void MotionWindow::update_mode() +void MotionHVWindow::update_mode() { global_range_w->update(plugin->config.global_range_w, MIN_RADIUS, @@ -274,7 +268,7 @@ void MotionWindow::update_mode() MIN_ROTATION, MAX_ROTATION); vectors->update(plugin->config.draw_vectors); - global->update(plugin->config.global); +// global->update(plugin->config.global); rotate->update(plugin->config.rotate); } @@ -290,7 +284,7 @@ void MotionWindow::update_mode() -GlobalRange::GlobalRange(MotionMain *plugin, +GlobalRange::GlobalRange(MotionHVMain *plugin, int x, int y, int *value) @@ -315,7 +309,7 @@ int GlobalRange::handle_event() -RotationRange::RotationRange(MotionMain *plugin, +RotationRange::RotationRange(MotionHVMain *plugin, int x, int y) : BC_IPot(x, @@ -338,7 +332,7 @@ int RotationRange::handle_event() -RotationCenter::RotationCenter(MotionMain *plugin, +RotationCenter::RotationCenter(MotionHVMain *plugin, int x, int y) : BC_IPot(x, @@ -363,7 +357,7 @@ int RotationCenter::handle_event() -BlockSize::BlockSize(MotionMain *plugin, +BlockSize::BlockSize(MotionHVMain *plugin, int x, int y, int *value) @@ -397,90 +391,90 @@ int BlockSize::handle_event() -GlobalSearchPositions::GlobalSearchPositions(MotionMain *plugin, - int x, - int y, - int w) - : BC_PopupMenu(x, - y, - w, - "", - 1) -{ - this->plugin = plugin; -} -void GlobalSearchPositions::create_objects() -{ - add_item(new BC_MenuItem("16")); - add_item(new BC_MenuItem("32")); - add_item(new BC_MenuItem("64")); - add_item(new BC_MenuItem("128")); - add_item(new BC_MenuItem("256")); - add_item(new BC_MenuItem("512")); - add_item(new BC_MenuItem("1024")); - add_item(new BC_MenuItem("2048")); - add_item(new BC_MenuItem("4096")); - add_item(new BC_MenuItem("8192")); - add_item(new BC_MenuItem("16384")); - add_item(new BC_MenuItem("32768")); - add_item(new BC_MenuItem("65536")); - add_item(new BC_MenuItem("131072")); - char string[BCTEXTLEN]; - sprintf(string, "%d", plugin->config.global_positions); - set_text(string); -} - -int GlobalSearchPositions::handle_event() -{ - plugin->config.global_positions = atoi(get_text()); - plugin->send_configure_change(); - return 1; -} - - - - - - - -RotationSearchPositions::RotationSearchPositions(MotionMain *plugin, - int x, - int y, - int w) - : BC_PopupMenu(x, - y, - w, - "", - 1) -{ - this->plugin = plugin; -} -void RotationSearchPositions::create_objects() -{ - add_item(new BC_MenuItem("4")); - add_item(new BC_MenuItem("8")); - add_item(new BC_MenuItem("16")); - add_item(new BC_MenuItem("32")); - char string[BCTEXTLEN]; - sprintf(string, "%d", plugin->config.rotate_positions); - set_text(string); -} - -int RotationSearchPositions::handle_event() -{ - plugin->config.rotate_positions = atoi(get_text()); - plugin->send_configure_change(); - return 1; -} - - - - - - - - -MotionMagnitude::MotionMagnitude(MotionMain *plugin, +// GlobalSearchPositions::GlobalSearchPositions(MotionHVMain *plugin, +// int x, +// int y, +// int w) +// : BC_PopupMenu(x, +// y, +// w, +// "", +// 1) +// { +// this->plugin = plugin; +// } +// void GlobalSearchPositions::create_objects() +// { +// add_item(new BC_MenuItem("16")); +// add_item(new BC_MenuItem("32")); +// add_item(new BC_MenuItem("64")); +// add_item(new BC_MenuItem("128")); +// add_item(new BC_MenuItem("256")); +// add_item(new BC_MenuItem("512")); +// add_item(new BC_MenuItem("1024")); +// add_item(new BC_MenuItem("2048")); +// add_item(new BC_MenuItem("4096")); +// add_item(new BC_MenuItem("8192")); +// add_item(new BC_MenuItem("16384")); +// add_item(new BC_MenuItem("32768")); +// add_item(new BC_MenuItem("65536")); +// add_item(new BC_MenuItem("131072")); +// char string[BCTEXTLEN]; +// sprintf(string, "%d", plugin->config.global_positions); +// set_text(string); +// } +// +// int GlobalSearchPositions::handle_event() +// { +// plugin->config.global_positions = atoi(get_text()); +// plugin->send_configure_change(); +// return 1; +// } +// +// +// +// +// +// +// +// RotationSearchPositions::RotationSearchPositions(MotionHVMain *plugin, +// int x, +// int y, +// int w) +// : BC_PopupMenu(x, +// y, +// w, +// "", +// 1) +// { +// this->plugin = plugin; +// } +// void RotationSearchPositions::create_objects() +// { +// add_item(new BC_MenuItem("4")); +// add_item(new BC_MenuItem("8")); +// add_item(new BC_MenuItem("16")); +// add_item(new BC_MenuItem("32")); +// char string[BCTEXTLEN]; +// sprintf(string, "%d", plugin->config.rotate_positions); +// set_text(string); +// } +// +// int RotationSearchPositions::handle_event() +// { +// plugin->config.rotate_positions = atoi(get_text()); +// plugin->send_configure_change(); +// return 1; +// } + + + + + + + + +MotionHVMagnitude::MotionHVMagnitude(MotionHVMain *plugin, int x, int y) : BC_IPot(x, @@ -492,7 +486,7 @@ MotionMagnitude::MotionMagnitude(MotionMain *plugin, this->plugin = plugin; } -int MotionMagnitude::handle_event() +int MotionHVMagnitude::handle_event() { plugin->config.magnitude = (int)get_value(); plugin->send_configure_change(); @@ -500,7 +494,7 @@ int MotionMagnitude::handle_event() } -MotionReturnSpeed::MotionReturnSpeed(MotionMain *plugin, +MotionHVReturnSpeed::MotionHVReturnSpeed(MotionHVMain *plugin, int x, int y) : BC_IPot(x, @@ -512,7 +506,7 @@ MotionReturnSpeed::MotionReturnSpeed(MotionMain *plugin, this->plugin = plugin; } -int MotionReturnSpeed::handle_event() +int MotionHVReturnSpeed::handle_event() { plugin->config.return_speed = (int)get_value(); plugin->send_configure_change(); @@ -521,7 +515,7 @@ int MotionReturnSpeed::handle_event() -MotionRMagnitude::MotionRMagnitude(MotionMain *plugin, +MotionHVRMagnitude::MotionHVRMagnitude(MotionHVMain *plugin, int x, int y) : BC_IPot(x, @@ -533,7 +527,7 @@ MotionRMagnitude::MotionRMagnitude(MotionMain *plugin, this->plugin = plugin; } -int MotionRMagnitude::handle_event() +int MotionHVRMagnitude::handle_event() { plugin->config.rotate_magnitude = (int)get_value(); plugin->send_configure_change(); @@ -542,7 +536,7 @@ int MotionRMagnitude::handle_event() -MotionRReturnSpeed::MotionRReturnSpeed(MotionMain *plugin, +MotionHVRReturnSpeed::MotionHVRReturnSpeed(MotionHVMain *plugin, int x, int y) : BC_IPot(x, @@ -554,7 +548,7 @@ MotionRReturnSpeed::MotionRReturnSpeed(MotionMain *plugin, this->plugin = plugin; } -int MotionRReturnSpeed::handle_event() +int MotionHVRReturnSpeed::handle_event() { plugin->config.rotate_return_speed = (int)get_value(); plugin->send_configure_change(); @@ -565,28 +559,28 @@ int MotionRReturnSpeed::handle_event() -MotionGlobal::MotionGlobal(MotionMain *plugin, - MotionWindow *gui, - int x, - int y) - : BC_CheckBox(x, - y, - plugin->config.global, - _("Track translation")) -{ - this->plugin = plugin; - this->gui = gui; -} +// MotionHVGlobal::MotionHVGlobal(MotionHVMain *plugin, +// MotionHVWindow *gui, +// int x, +// int y) +// : BC_CheckBox(x, +// y, +// plugin->config.global, +// _("Track translation")) +// { +// this->plugin = plugin; +// this->gui = gui; +// } +// +// int MotionHVGlobal::handle_event() +// { +// plugin->config.global = get_value(); +// plugin->send_configure_change(); +// return 1; +// } -int MotionGlobal::handle_event() -{ - plugin->config.global = get_value(); - plugin->send_configure_change(); - return 1; -} - -MotionRotate::MotionRotate(MotionMain *plugin, - MotionWindow *gui, +MotionHVRotate::MotionHVRotate(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_CheckBox(x, @@ -598,7 +592,7 @@ MotionRotate::MotionRotate(MotionMain *plugin, this->gui = gui; } -int MotionRotate::handle_event() +int MotionHVRotate::handle_event() { plugin->config.rotate = get_value(); plugin->send_configure_change(); @@ -609,8 +603,8 @@ int MotionRotate::handle_event() -MotionBlockX::MotionBlockX(MotionMain *plugin, - MotionWindow *gui, +MotionHVBlockX::MotionHVBlockX(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_FPot(x, @@ -623,7 +617,7 @@ MotionBlockX::MotionBlockX(MotionMain *plugin, this->gui = gui; } -int MotionBlockX::handle_event() +int MotionHVBlockX::handle_event() { plugin->config.block_x = get_value(); gui->block_x_text->update((float)plugin->config.block_x); @@ -634,8 +628,8 @@ int MotionBlockX::handle_event() -MotionBlockY::MotionBlockY(MotionMain *plugin, - MotionWindow *gui, +MotionHVBlockY::MotionHVBlockY(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_FPot(x, @@ -648,7 +642,7 @@ MotionBlockY::MotionBlockY(MotionMain *plugin, this->gui = gui; } -int MotionBlockY::handle_event() +int MotionHVBlockY::handle_event() { plugin->config.block_y = get_value(); gui->block_y_text->update((float)plugin->config.block_y); @@ -656,8 +650,8 @@ int MotionBlockY::handle_event() return 1; } -MotionBlockXText::MotionBlockXText(MotionMain *plugin, - MotionWindow *gui, +MotionHVBlockXText::MotionHVBlockXText(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_TextBox(x, @@ -671,7 +665,7 @@ MotionBlockXText::MotionBlockXText(MotionMain *plugin, set_precision(4); } -int MotionBlockXText::handle_event() +int MotionHVBlockXText::handle_event() { plugin->config.block_x = atof(get_text()); gui->block_x->update(plugin->config.block_x); @@ -682,8 +676,8 @@ int MotionBlockXText::handle_event() -MotionBlockYText::MotionBlockYText(MotionMain *plugin, - MotionWindow *gui, +MotionHVBlockYText::MotionHVBlockYText(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_TextBox(x, @@ -697,7 +691,7 @@ MotionBlockYText::MotionBlockYText(MotionMain *plugin, set_precision(4); } -int MotionBlockYText::handle_event() +int MotionHVBlockYText::handle_event() { plugin->config.block_y = atof(get_text()); gui->block_y->update(plugin->config.block_y); @@ -720,8 +714,8 @@ int MotionBlockYText::handle_event() -MotionDrawVectors::MotionDrawVectors(MotionMain *plugin, - MotionWindow *gui, +MotionHVDrawVectors::MotionHVDrawVectors(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_CheckBox(x, @@ -733,7 +727,7 @@ MotionDrawVectors::MotionDrawVectors(MotionMain *plugin, this->plugin = plugin; } -int MotionDrawVectors::handle_event() +int MotionHVDrawVectors::handle_event() { plugin->config.draw_vectors = get_value(); plugin->send_configure_change(); @@ -747,13 +741,13 @@ int MotionDrawVectors::handle_event() -TrackSingleFrame::TrackSingleFrame(MotionMain *plugin, - MotionWindow *gui, +TrackSingleFrame::TrackSingleFrame(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_Radial(x, y, - plugin->config.tracking_object == MotionScan::TRACK_SINGLE, + plugin->config.tracking_object == MotionHVScan::TRACK_SINGLE, _("Track single frame")) { this->plugin = plugin; @@ -762,7 +756,7 @@ TrackSingleFrame::TrackSingleFrame(MotionMain *plugin, int TrackSingleFrame::handle_event() { - plugin->config.tracking_object = MotionScan::TRACK_SINGLE; + plugin->config.tracking_object = MotionHVScan::TRACK_SINGLE; gui->track_previous->update(0); gui->previous_same->update(0); gui->track_frame_number->enable(); @@ -777,15 +771,15 @@ int TrackSingleFrame::handle_event() -TrackFrameNumber::TrackFrameNumber(MotionMain *plugin, - MotionWindow *gui, +TrackFrameNumber::TrackFrameNumber(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_TextBox(x, y, 100, 1, plugin->config.track_frame) { this->plugin = plugin; this->gui = gui; - if(plugin->config.tracking_object != MotionScan::TRACK_SINGLE) disable(); + if(plugin->config.tracking_object != MotionHVScan::TRACK_SINGLE) disable(); } int TrackFrameNumber::handle_event() @@ -801,13 +795,13 @@ int TrackFrameNumber::handle_event() -TrackPreviousFrame::TrackPreviousFrame(MotionMain *plugin, - MotionWindow *gui, +TrackPreviousFrame::TrackPreviousFrame(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_Radial(x, y, - plugin->config.tracking_object == MotionScan::TRACK_PREVIOUS, + plugin->config.tracking_object == MotionHVScan::TRACK_PREVIOUS, _("Track previous frame")) { this->plugin = plugin; @@ -815,7 +809,7 @@ TrackPreviousFrame::TrackPreviousFrame(MotionMain *plugin, } int TrackPreviousFrame::handle_event() { - plugin->config.tracking_object = MotionScan::TRACK_PREVIOUS; + plugin->config.tracking_object = MotionHVScan::TRACK_PREVIOUS; gui->track_single->update(0); gui->previous_same->update(0); gui->track_frame_number->disable(); @@ -830,13 +824,13 @@ int TrackPreviousFrame::handle_event() -PreviousFrameSameBlock::PreviousFrameSameBlock(MotionMain *plugin, - MotionWindow *gui, +PreviousFrameSameBlock::PreviousFrameSameBlock(MotionHVMain *plugin, + MotionHVWindow *gui, int x, int y) : BC_Radial(x, y, - plugin->config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK, + plugin->config.tracking_object == MotionHVScan::PREVIOUS_SAME_BLOCK, _("Previous frame same block")) { this->plugin = plugin; @@ -844,7 +838,7 @@ PreviousFrameSameBlock::PreviousFrameSameBlock(MotionMain *plugin, } int PreviousFrameSameBlock::handle_event() { - plugin->config.tracking_object = MotionScan::PREVIOUS_SAME_BLOCK; + plugin->config.tracking_object = MotionHVScan::PREVIOUS_SAME_BLOCK; gui->track_single->update(0); gui->track_previous->update(0); gui->track_frame_number->disable(); @@ -859,7 +853,7 @@ int PreviousFrameSameBlock::handle_event() -MasterLayer::MasterLayer(MotionMain *plugin, MotionWindow *gui, int x, int y) +MasterLayer::MasterLayer(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y) : BC_PopupMenu(x, y, calculate_w(gui), @@ -893,7 +887,7 @@ char* MasterLayer::to_text(int mode) return mode ? _("Bottom") : _("Top"); } -int MasterLayer::calculate_w(MotionWindow *gui) +int MasterLayer::calculate_w(MotionHVWindow *gui) { int result = 0; result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0))); @@ -908,7 +902,7 @@ int MasterLayer::calculate_w(MotionWindow *gui) -ActionType::ActionType(MotionMain *plugin, MotionWindow *gui, int x, int y) +ActionType::ActionType(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y) : BC_PopupMenu(x, y, calculate_w(gui), @@ -927,52 +921,49 @@ int ActionType::handle_event() void ActionType::create_objects() { - add_item(new BC_MenuItem(to_text(MotionScan::TRACK))); - add_item(new BC_MenuItem(to_text(MotionScan::TRACK_PIXEL))); - add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE))); - add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE_PIXEL))); - add_item(new BC_MenuItem(to_text(MotionScan::NOTHING))); + add_item(new BC_MenuItem(to_text(MotionHVScan::TRACK))); + add_item(new BC_MenuItem(to_text(MotionHVScan::TRACK_PIXEL))); + add_item(new BC_MenuItem(to_text(MotionHVScan::STABILIZE))); + add_item(new BC_MenuItem(to_text(MotionHVScan::STABILIZE_PIXEL))); + add_item(new BC_MenuItem(to_text(MotionHVScan::NOTHING))); } int ActionType::from_text(char *text) { - if(!strcmp(text, _("Track Subpixel"))) return MotionScan::TRACK; - if(!strcmp(text, _("Track Pixel"))) return MotionScan::TRACK_PIXEL; - if(!strcmp(text, _("Stabilize Subpixel"))) return MotionScan::STABILIZE; - if(!strcmp(text, _("Stabilize Pixel"))) return MotionScan::STABILIZE_PIXEL; - if(!strcmp(text, _("Do Nothing"))) return MotionScan::NOTHING; + if(!strcmp(text, _("Track Subpixel"))) return MotionHVScan::TRACK; + if(!strcmp(text, _("Track Pixel"))) return MotionHVScan::TRACK_PIXEL; + if(!strcmp(text, _("Stabilize Subpixel"))) return MotionHVScan::STABILIZE; + if(!strcmp(text, _("Stabilize Pixel"))) return MotionHVScan::STABILIZE_PIXEL; + //if(!strcmp(text, _("Do Nothing"))) return MotionHVScan::NOTHING; + return MotionHVScan::NOTHING; } char* ActionType::to_text(int mode) { switch(mode) { - case MotionScan::TRACK: + case MotionHVScan::TRACK: return _("Track Subpixel"); - break; - case MotionScan::TRACK_PIXEL: + case MotionHVScan::TRACK_PIXEL: return _("Track Pixel"); - break; - case MotionScan::STABILIZE: + case MotionHVScan::STABILIZE: return _("Stabilize Subpixel"); - break; - case MotionScan::STABILIZE_PIXEL: + case MotionHVScan::STABILIZE_PIXEL: return _("Stabilize Pixel"); - break; - case MotionScan::NOTHING: + default: + case MotionHVScan::NOTHING: return _("Do Nothing"); - break; } } -int ActionType::calculate_w(MotionWindow *gui) +int ActionType::calculate_w(MotionHVWindow *gui) { int result = 0; - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK))); - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK_PIXEL))); - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE))); - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE_PIXEL))); - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NOTHING))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::TRACK))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::TRACK_PIXEL))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::STABILIZE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::STABILIZE_PIXEL))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::NOTHING))); return result + 50; } @@ -980,7 +971,7 @@ int ActionType::calculate_w(MotionWindow *gui) -TrackingType::TrackingType(MotionMain *plugin, MotionWindow *gui, int x, int y) +TrackingType::TrackingType(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y) : BC_PopupMenu(x, y, calculate_w(gui), @@ -999,46 +990,44 @@ int TrackingType::handle_event() void TrackingType::create_objects() { - add_item(new BC_MenuItem(to_text(MotionScan::NO_CALCULATE))); - add_item(new BC_MenuItem(to_text(MotionScan::CALCULATE))); - add_item(new BC_MenuItem(to_text(MotionScan::SAVE))); - add_item(new BC_MenuItem(to_text(MotionScan::LOAD))); + add_item(new BC_MenuItem(to_text(MotionHVScan::NO_CALCULATE))); + add_item(new BC_MenuItem(to_text(MotionHVScan::CALCULATE))); + add_item(new BC_MenuItem(to_text(MotionHVScan::SAVE))); + add_item(new BC_MenuItem(to_text(MotionHVScan::LOAD))); } int TrackingType::from_text(char *text) { - if(!strcmp(text, _("Don't Calculate"))) return MotionScan::NO_CALCULATE; - if(!strcmp(text, _("Recalculate"))) return MotionScan::CALCULATE; - if(!strcmp(text, _("Save coords to /tmp"))) return MotionScan::SAVE; - if(!strcmp(text, _("Load coords from /tmp"))) return MotionScan::LOAD; + if(!strcmp(text, _("Save coords to /tmp"))) return MotionHVScan::SAVE; + if(!strcmp(text, _("Load coords from /tmp"))) return MotionHVScan::LOAD; + if(!strcmp(text, _("Recalculate"))) return MotionHVScan::CALCULATE; + //if(!strcmp(text, _("Don't Calculate"))) return MotionHVScan::NO_CALCULATE; + return MotionHVScan::NO_CALCULATE; } char* TrackingType::to_text(int mode) { switch(mode) { - case MotionScan::NO_CALCULATE: - return _("Don't Calculate"); - break; - case MotionScan::CALCULATE: - return _("Recalculate"); - break; - case MotionScan::SAVE: + case MotionHVScan::SAVE: return _("Save coords to /tmp"); - break; - case MotionScan::LOAD: + case MotionHVScan::LOAD: return _("Load coords from /tmp"); - break; + case MotionHVScan::CALCULATE: + return _("Recalculate"); + default: + case MotionHVScan::NO_CALCULATE: + return _("Don't Calculate"); } } -int TrackingType::calculate_w(MotionWindow *gui) +int TrackingType::calculate_w(MotionHVWindow *gui) { int result = 0; - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NO_CALCULATE))); - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::CALCULATE))); - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::SAVE))); - result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::LOAD))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::NO_CALCULATE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::CALCULATE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::SAVE))); + result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionHVScan::LOAD))); return result + 50; } @@ -1051,7 +1040,7 @@ int TrackingType::calculate_w(MotionWindow *gui) -TrackDirection::TrackDirection(MotionMain *plugin, MotionWindow *gui, int x, int y) +TrackDirection::TrackDirection(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y) : BC_PopupMenu(x, y, calculate_w(gui), @@ -1090,7 +1079,7 @@ char* TrackDirection::to_text(int horizontal_only, int vertical_only) return _("Both"); } -int TrackDirection::calculate_w(MotionWindow *gui) +int TrackDirection::calculate_w(MotionHVWindow *gui) { int result = 0; result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0))); diff --git a/cinelerra-5.1/plugins/motion-hv/motionwindow-hv.h b/cinelerra-5.1/plugins/motion-hv/motionwindow-hv.h new file mode 100644 index 00000000..220b7426 --- /dev/null +++ b/cinelerra-5.1/plugins/motion-hv/motionwindow-hv.h @@ -0,0 +1,385 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 "guicast.h" +#include "motion-hv.inc" + +class MasterLayer : public BC_PopupMenu +{ +public: + MasterLayer(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionHVWindow *gui); + static int from_text(char *text); + static char* to_text(int mode); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class ActionType : public BC_PopupMenu +{ +public: + ActionType(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionHVWindow *gui); + static int from_text(char *text); + static char* to_text(int mode); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class TrackingType : public BC_PopupMenu +{ +public: + TrackingType(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionHVWindow *gui); + static int from_text(char *text); + static char* to_text(int mode); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class TrackDirection : public BC_PopupMenu +{ +public: + TrackDirection(MotionHVMain *plugin, MotionHVWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + static int calculate_w(MotionHVWindow *gui); + static void from_text(int *horizontal_only, int *vertical_only, char *text); + static char* to_text(int horizontal_only, int vertical_only); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + + +class TrackSingleFrame : public BC_Radial +{ +public: + TrackSingleFrame(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class TrackFrameNumber : public BC_TextBox +{ +public: + TrackFrameNumber(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class TrackPreviousFrame : public BC_Radial +{ +public: + TrackPreviousFrame(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class PreviousFrameSameBlock : public BC_Radial +{ +public: + PreviousFrameSameBlock(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class GlobalRange : public BC_IPot +{ +public: + GlobalRange(MotionHVMain *plugin, + int x, + int y, + int *value); + int handle_event(); + MotionHVMain *plugin; + int *value; +}; + +class RotationRange : public BC_IPot +{ +public: + RotationRange(MotionHVMain *plugin, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; +}; + +class RotationCenter : public BC_IPot +{ +public: + RotationCenter(MotionHVMain *plugin, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; +}; + +class BlockSize : public BC_IPot +{ +public: + BlockSize(MotionHVMain *plugin, + int x, + int y, + int *value); + int handle_event(); + MotionHVMain *plugin; + int *value; +}; + +class MotionHVBlockX : public BC_FPot +{ +public: + MotionHVBlockX(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVWindow *gui; + MotionHVMain *plugin; +}; + +class MotionHVBlockY : public BC_FPot +{ +public: + MotionHVBlockY(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVWindow *gui; + MotionHVMain *plugin; +}; + +class MotionHVBlockXText : public BC_TextBox +{ +public: + MotionHVBlockXText(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVWindow *gui; + MotionHVMain *plugin; +}; + +class MotionHVBlockYText : public BC_TextBox +{ +public: + MotionHVBlockYText(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVWindow *gui; + MotionHVMain *plugin; +}; + +// class GlobalSearchPositions : public BC_PopupMenu +// { +// public: +// GlobalSearchPositions(MotionHVMain *plugin, +// int x, +// int y, +// int w); +// void create_objects(); +// int handle_event(); +// MotionHVMain *plugin; +// }; +// +// class RotationSearchPositions : public BC_PopupMenu +// { +// public: +// RotationSearchPositions(MotionHVMain *plugin, +// int x, +// int y, +// int w); +// void create_objects(); +// int handle_event(); +// MotionHVMain *plugin; +// }; + +class MotionHVMagnitude : public BC_IPot +{ +public: + MotionHVMagnitude(MotionHVMain *plugin, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; +}; + +class MotionHVRMagnitude : public BC_IPot +{ +public: + MotionHVRMagnitude(MotionHVMain *plugin, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; +}; + +class MotionHVReturnSpeed : public BC_IPot +{ +public: + MotionHVReturnSpeed(MotionHVMain *plugin, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; +}; + + +class MotionHVRReturnSpeed : public BC_IPot +{ +public: + MotionHVRReturnSpeed(MotionHVMain *plugin, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; +}; + + +class MotionHVDrawVectors : public BC_CheckBox +{ +public: + MotionHVDrawVectors(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVMain *plugin; + MotionHVWindow *gui; +}; + +class AddTrackedFrameOffset : public BC_CheckBox +{ +public: + AddTrackedFrameOffset(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVWindow *gui; + MotionHVMain *plugin; +}; + +// class MotionHVGlobal : public BC_CheckBox +// { +// public: +// MotionHVGlobal(MotionHVMain *plugin, +// MotionHVWindow *gui, +// int x, +// int y); +// int handle_event(); +// MotionHVWindow *gui; +// MotionHVMain *plugin; +// }; + +class MotionHVRotate : public BC_CheckBox +{ +public: + MotionHVRotate(MotionHVMain *plugin, + MotionHVWindow *gui, + int x, + int y); + int handle_event(); + MotionHVWindow *gui; + MotionHVMain *plugin; +}; + + + +class MotionHVWindow : public PluginClientWindow +{ +public: + MotionHVWindow(MotionHVMain *plugin); + ~MotionHVWindow(); + + void create_objects(); + void update_mode(); + char* get_radius_title(); + + GlobalRange *global_range_w; + GlobalRange *global_range_h; + RotationRange *rotation_range; + RotationCenter *rotation_center; + BlockSize *global_block_w; + BlockSize *global_block_h; + BlockSize *rotation_block_w; + BlockSize *rotation_block_h; + MotionHVBlockX *block_x; + MotionHVBlockY *block_y; + MotionHVBlockXText *block_x_text; + MotionHVBlockYText *block_y_text; +// GlobalSearchPositions *global_search_positions; +// RotationSearchPositions *rotation_search_positions; + MotionHVMagnitude *magnitude; + MotionHVRMagnitude *rotate_magnitude; + MotionHVReturnSpeed *return_speed; + MotionHVRReturnSpeed *rotate_return_speed; + ActionType *action_type; + MotionHVDrawVectors *vectors; +// MotionHVGlobal *global; + MotionHVRotate *rotate; + AddTrackedFrameOffset *addtrackedframeoffset; + TrackSingleFrame *track_single; + TrackFrameNumber *track_frame_number; + TrackPreviousFrame *track_previous; + PreviousFrameSameBlock *previous_same; + MasterLayer *master_layer; + TrackingType *tracking_type; + TrackDirection *track_direction; + + MotionHVMain *plugin; +}; + + + + + + + + + diff --git a/cinelerra-5.1/plugins/motion.new/motionwindow.inc b/cinelerra-5.1/plugins/motion-hv/motionwindow-hv.inc similarity index 89% rename from cinelerra-5.1/plugins/motion.new/motionwindow.inc rename to cinelerra-5.1/plugins/motion-hv/motionwindow-hv.inc index 8fbef467..160075ba 100644 --- a/cinelerra-5.1/plugins/motion.new/motionwindow.inc +++ b/cinelerra-5.1/plugins/motion-hv/motionwindow-hv.inc @@ -19,10 +19,10 @@ * */ -#ifndef MOTIONWINDOW_INC -#define MOTIONWINDOW_INC +#ifndef MOTIONWINDOWHV_INC +#define MOTIONWINDOWHV_INC -class MotionWindow; -class MotionThread; +class MotionHVWindow; +class MotionHVThread; #endif diff --git a/cinelerra-5.1/plugins/motion-hv/picon.png b/cinelerra-5.1/plugins/motion-hv/picon.png new file mode 100644 index 00000000..01b282a6 Binary files /dev/null and b/cinelerra-5.1/plugins/motion-hv/picon.png differ diff --git a/cinelerra-5.1/plugins/motion-hv/theme_suv.png b/cinelerra-5.1/plugins/motion-hv/theme_suv.png new file mode 100644 index 00000000..e2816133 Binary files /dev/null and b/cinelerra-5.1/plugins/motion-hv/theme_suv.png differ diff --git a/cinelerra-5.1/plugins/motion.new/Makefile b/cinelerra-5.1/plugins/motion.new/Makefile deleted file mode 100644 index 93ba09b6..00000000 --- a/cinelerra-5.1/plugins/motion.new/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -include ../../plugin_defs - -OBJS := \ - $(OBJDIR)/motion.o \ - $(OBJDIR)/motionscan.o \ - $(OBJDIR)/motionwindow.o - -PLUGIN = motion - -include ../../plugin_config - -$(OBJDIR)/motion.o: motion.C -$(OBJDIR)/motionscan.o: motionscan.C -$(OBJDIR)/motionwindow.o: motionwindow.C diff --git a/cinelerra-5.1/plugins/motion.new/motionscan.C b/cinelerra-5.1/plugins/motion.new/motionscan.C deleted file mode 100644 index a04b9b4c..00000000 --- a/cinelerra-5.1/plugins/motion.new/motionscan.C +++ /dev/null @@ -1,1090 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 "../downsample/downsampleengine.h" -//#include "motion.h" -#include "motionscan.h" -#include "mutex.h" -#include "vframe.h" - -#include - -// The module which does the actual scanning - -MotionScanPackage::MotionScanPackage() - : LoadPackage() -{ - valid = 1; -} - - - - - - -MotionScanUnit::MotionScanUnit(MotionScan *server) - : LoadClient(server) -{ - this->server = server; - cache_lock = new Mutex("MotionScanUnit::cache_lock"); -} - -MotionScanUnit::~MotionScanUnit() -{ - delete cache_lock; -} - - - -void MotionScanUnit::process_package(LoadPackage *package) -{ - MotionScanPackage *pkg = (MotionScanPackage*)package; - int w = server->current_frame->get_w(); - int h = server->current_frame->get_h(); - int color_model = server->current_frame->get_color_model(); - int pixel_size = BC_CModels::calculate_pixelsize(color_model); - int row_bytes = server->current_frame->get_bytes_per_line(); - - - - - - - - - - - - -// Single pixel - if(!server->subpixel) - { -// Try cache - pkg->difference1 = server->get_cache(pkg->search_x, pkg->search_y); - if(pkg->difference1 < 0) - { -//printf("MotionScanUnit::process_package 1 search_x=%d search_y=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d x_steps=%d y_steps=%d\n", -//pkg->search_x, pkg->search_y, pkg->scan_x1, pkg->scan_y1, pkg->scan_x2, pkg->scan_y2, server->x_steps, server->y_steps); -// Pointers to first pixel in each block - unsigned char *prev_ptr = server->previous_frame->get_rows()[ - pkg->search_y] + - pkg->search_x * pixel_size; - unsigned char *current_ptr = server->current_frame->get_rows()[ - pkg->block_y1] + - pkg->block_x1 * pixel_size; - -// Scan block - pkg->difference1 = MotionScan::abs_diff(prev_ptr, - current_ptr, - row_bytes, - pkg->block_x2 - pkg->block_x1, - pkg->block_y2 - pkg->block_y1, - color_model); - -// printf("MotionScanUnit::process_package %d search_x=%d search_y=%d diff=%lld\n", -// __LINE__, server->block_x1 - pkg->search_x, server->block_y1 - pkg->search_y, pkg->difference1); - server->put_cache(pkg->search_x, pkg->search_y, pkg->difference1); - } - } - - - - - - - - else - - - - - - - - -// Sub pixel - { - unsigned char *prev_ptr = server->previous_frame->get_rows()[ - pkg->search_y] + - pkg->search_x * pixel_size; - unsigned char *current_ptr = server->current_frame->get_rows()[ - pkg->block_y1] + - pkg->block_x1 * pixel_size; - -// With subpixel, there are two ways to compare each position, one by shifting -// the previous frame and two by shifting the current frame. - pkg->difference1 = MotionScan::abs_diff_sub(prev_ptr, - current_ptr, - row_bytes, - pkg->block_x2 - pkg->block_x1, - pkg->block_y2 - pkg->block_y1, - color_model, - pkg->sub_x, - pkg->sub_y); - pkg->difference2 = MotionScan::abs_diff_sub(current_ptr, - prev_ptr, - row_bytes, - pkg->block_x2 - pkg->block_x1, - pkg->block_y2 - pkg->block_y1, - color_model, - pkg->sub_x, - pkg->sub_y); -// printf("MotionScanUnit::process_package sub_x=%d sub_y=%d search_x=%d search_y=%d diff1=%lld diff2=%lld\n", -// sub_x, -// sub_y, -// search_x, -// search_y, -// pkg->difference1, -// pkg->difference2); - } - - - - -} - - - - - - - - - - -int64_t MotionScanUnit::get_cache(int x, int y) -{ - int64_t result = -1; - cache_lock->lock("MotionScanUnit::get_cache"); - for(int i = 0; i < cache.total; i++) - { - MotionScanCache *ptr = cache.values[i]; - if(ptr->x == x && ptr->y == y) - { - result = ptr->difference; - break; - } - } - cache_lock->unlock(); - return result; -} - -void MotionScanUnit::put_cache(int x, int y, int64_t difference) -{ - MotionScanCache *ptr = new MotionScanCache(x, y, difference); - cache_lock->lock("MotionScanUnit::put_cache"); - cache.append(ptr); - cache_lock->unlock(); -} - - - - - - - - - - - -MotionScan::MotionScan(int total_clients, - int total_packages) - : LoadServer( -//1, 1 -total_clients, total_packages -) -{ - test_match = 1; - cache_lock = new Mutex("MotionScan::cache_lock"); - downsampled_previous = 0; - downsampled_current = 0; -// downsample = 0; -} - -MotionScan::~MotionScan() -{ - delete cache_lock; - delete downsampled_previous; - delete downsampled_current; -// delete downsample; -} - - -void MotionScan::init_packages() -{ -// Set package coords -//printf("MotionScan::init_packages %d %d\n", __LINE__, get_total_packages()); - for(int i = 0; i < get_total_packages(); i++) - { - MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); - - pkg->block_x1 = block_x1; - pkg->block_x2 = block_x2; - pkg->block_y1 = block_y1; - pkg->block_y2 = block_y2; - pkg->scan_x1 = scan_x1; - pkg->scan_x2 = scan_x2; - pkg->scan_y1 = scan_y1; - pkg->scan_y2 = scan_y2; - pkg->step = i; - pkg->difference1 = 0; - pkg->difference2 = 0; - pkg->dx = 0; - pkg->dy = 0; - pkg->valid = 1; - - if(!subpixel) - { - pkg->search_x = pkg->scan_x1 + (pkg->step % x_steps) * - (scan_x2 - scan_x1) / x_steps; - pkg->search_y = pkg->scan_y1 + (pkg->step / x_steps) * - (scan_y2 - scan_y1) / y_steps; - pkg->sub_x = 0; - pkg->sub_y = 0; - } - else - { - pkg->sub_x = pkg->step % (OVERSAMPLE * 2); - pkg->sub_y = pkg->step / (OVERSAMPLE * 2); - - if(horizontal_only) - { - pkg->sub_y = 0; - } - - if(vertical_only) - { - pkg->sub_x = 0; - } - - pkg->search_x = pkg->scan_x1 + pkg->sub_x / OVERSAMPLE + 1; - pkg->search_y = pkg->scan_y1 + pkg->sub_y / OVERSAMPLE + 1; - pkg->sub_x %= OVERSAMPLE; - pkg->sub_y %= OVERSAMPLE; - - - -// printf("MotionScan::init_packages %d i=%d search_x=%d search_y=%d sub_x=%d sub_y=%d\n", -// __LINE__, -// i, -// pkg->search_x, -// pkg->search_y, -// pkg->sub_x, -// pkg->sub_y); - } - -// printf("MotionScan::init_packages %d %d,%d %d,%d %d,%d\n", -// __LINE__, -// scan_x1, -// scan_x2, -// scan_y1, -// scan_y2, -// pkg->search_x, -// pkg->search_y); - } -} - -LoadClient* MotionScan::new_client() -{ - return new MotionScanUnit(this); -} - -LoadPackage* MotionScan::new_package() -{ - return new MotionScanPackage; -} - - -void MotionScan::set_test_match(int value) -{ - this->test_match = value; -} - -void MotionScan::scan_frame(VFrame *previous_frame, - VFrame *current_frame, - int global_range_w, - int global_range_h, - int global_block_w, - int global_block_h, - double block_x, - double block_y, - int frame_type, - int tracking_type, - int action_type, - int horizontal_only, - int vertical_only, - int source_position, - int total_steps, - int total_dx, - int total_dy, - int global_origin_x, - int global_origin_y) -{ - this->previous_frame_arg = previous_frame; - this->current_frame_arg = current_frame; - this->horizontal_only = horizontal_only; - this->vertical_only = vertical_only; - this->previous_frame = previous_frame_arg; - this->current_frame = current_frame_arg; - this->global_origin_x = global_origin_x; - this->global_origin_y = global_origin_y; - subpixel = 0; - - cache.remove_all_objects(); - -// Single macroblock - int w = current_frame->get_w(); - int h = current_frame->get_h(); - -// Initial search parameters - int scan_w = w * global_range_w / 100; - int scan_h = h * global_range_h / 100; - int block_w = w * global_block_w / 100; - int block_h = h * global_block_h / 100; - -// Location of block in previous frame - block_x1 = (int)(w * block_x / 100 - block_w / 2); - block_y1 = (int)(h * block_y / 100 - block_h / 2); - block_x2 = (int)(w * block_x / 100 + block_w / 2); - block_y2 = (int)(h * block_y / 100 + block_h / 2); - -// Offset to location of previous block. This offset needn't be very accurate -// since it's the offset of the previous image and current image we want. - if(frame_type == MotionScan::TRACK_PREVIOUS) - { - block_x1 += total_dx / OVERSAMPLE; - block_y1 += total_dy / OVERSAMPLE; - block_x2 += total_dx / OVERSAMPLE; - block_y2 += total_dy / OVERSAMPLE; - } - - skip = 0; - - switch(tracking_type) - { -// Don't calculate - case MotionScan::NO_CALCULATE: - dx_result = 0; - dy_result = 0; - skip = 1; - break; - - case MotionScan::LOAD: - { -//printf("MotionScan::scan_frame %d\n", __LINE__); -// Load result from disk - char string[BCTEXTLEN]; - sprintf(string, "%s%06d", - MOTION_FILE, - source_position); - FILE *input = fopen(string, "r"); - if(input) - { - fscanf(input, - "%d %d", - &dx_result, - &dy_result); - fclose(input); - skip = 1; - } - break; - } - -// Scan from scratch - default: - skip = 0; - break; - } - - if(!skip && test_match) - { - if(previous_frame->data_matches(current_frame)) - { -printf("MotionScan::scan_frame: data matches. skipping.\n"); - dx_result = 0; - dy_result = 0; - skip = 1; - } - } - -// Perform scan - if(!skip) - { -//printf("MotionScan::scan_frame %d\n", __LINE__); -// Location of block in current frame - int origin_offset_x = this->global_origin_x * w / 100; - int origin_offset_y = this->global_origin_y * h / 100; - int x_result = block_x1 + origin_offset_x; - int y_result = block_y1 + origin_offset_y; - -// printf("MotionScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", -// block_x1 + block_w / 2, -// block_y1 + block_h / 2, -// block_w, -// block_h, -// block_x1, -// block_y1, -// block_x2, -// block_y2); - - while(1) - { -// Cache needs to be cleared if downsampling is used because the sums of -// different downsamplings can't be compared. -// Subpixel never uses the cache. -// cache.remove_all_objects(); - scan_x1 = x_result - scan_w / 2; - scan_y1 = y_result - scan_h / 2; - scan_x2 = x_result + scan_w / 2; - scan_y2 = y_result + scan_h / 2; - - - -// Zero out requested values - if(horizontal_only) - { - scan_y1 = block_y1; - scan_y2 = block_y1 + 1; - } - if(vertical_only) - { - scan_x1 = block_x1; - scan_x2 = block_x1 + 1; - } - -// printf("MotionScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", -// block_x1, -// block_y1, -// block_x2, -// block_y2, -// scan_x1, -// scan_y1, -// scan_x2, -// scan_y2); -// Clamp the block coords before the scan so we get useful scan coords. - clamp_scan(w, - h, - &block_x1, - &block_y1, - &block_x2, - &block_y2, - &scan_x1, - &scan_y1, - &scan_x2, - &scan_y2, - 0); -// printf("MotionScan::scan_frame 1 %d block_x1=%d block_y1=%d block_x2=%d block_y2=%d\n scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d\n x_result=%d y_result=%d\n", -// __LINE__, -// block_x1, -// block_y1, -// block_x2, -// block_y2, -// scan_x1, -// scan_y1, -// scan_x2, -// scan_y2, -// x_result, -// y_result); - - -// Give up if invalid coords. - if(scan_y2 <= scan_y1 || - scan_x2 <= scan_x1 || - block_x2 <= block_x1 || - block_y2 <= block_y1) - break; - -// For subpixel, the top row and left column are skipped - if(subpixel) - { - -//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result); -// Scan every subpixel in a 2 pixel * 2 pixel square - total_pixels = (2 * OVERSAMPLE) * (2 * OVERSAMPLE); - - this->total_steps = total_pixels; -// These aren't used in subpixel - this->x_steps = OVERSAMPLE * 2; - this->y_steps = OVERSAMPLE * 2; - - set_package_count(this->total_steps); - process_packages(); - -// Get least difference - int64_t min_difference = -1; - for(int i = 0; i < get_total_packages(); i++) - { - MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); -//printf("MotionScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", -//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2); - if(pkg->difference1 < min_difference || min_difference == -1) - { - min_difference = pkg->difference1; - -// The sub coords are 1 pixel up & left of the block coords - x_result = pkg->search_x * OVERSAMPLE + pkg->sub_x; - y_result = pkg->search_y * OVERSAMPLE + pkg->sub_y; - - -// Fill in results - dx_result = block_x1 * OVERSAMPLE - x_result; - dy_result = block_y1 * OVERSAMPLE - y_result; -//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", -//__LINE__, dx_result, dy_result, min_difference); - } - - if(pkg->difference2 < min_difference) - { - min_difference = pkg->difference2; - - x_result = pkg->search_x * OVERSAMPLE - pkg->sub_x; - y_result = pkg->search_y * OVERSAMPLE - pkg->sub_y; - - dx_result = block_x1 * OVERSAMPLE - x_result; - dy_result = block_y1 * OVERSAMPLE - y_result; -//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", -//__LINE__, dx_result, dy_result, min_difference); - } - } - - break; - } - else -// Single pixel - { - total_pixels = (scan_x2 - scan_x1) * (scan_y2 - scan_y1); - this->total_steps = MIN(total_steps, total_pixels); - - if(this->total_steps == total_pixels) - { - x_steps = scan_x2 - scan_x1; - y_steps = scan_y2 - scan_y1; - } - else - { - x_steps = (int)sqrt(this->total_steps); - y_steps = (int)sqrt(this->total_steps); - } - -// Use downsampled images -// if(scan_x2 - scan_x1 > x_steps * 4 || -// scan_y2 - scan_y1 > y_steps * 4) -// { -// printf("MotionScan::scan_frame %d total_pixels=%d total_steps=%d x_steps=%d y_steps=%d x y steps=%d\n", -// __LINE__, -// total_pixels, -// total_steps, -// x_steps, -// y_steps, -// x_steps * y_steps); -// -// if(!downsampled_previous || -// !downsampled_previous->equivalent(previous_frame_arg)) -// { -// delete downsampled_previous; -// downsampled_previous = new VFrame(*previous_frame_arg); -// } -// -// if(!downsampled_current || -// !downsampled_current->equivalent(current_frame_arg)) -// { -// delete downsampled_current; -// downsampled_current = new VFrame(*current_frame_arg); -// } -// -// -// if(!downsample) -// downsample = new DownSampleServer(get_total_clients(), -// get_total_clients()); -// downsample->process_frame(downsampled_previous, -// previous_frame_arg, -// 1, -// 1, -// 1, -// 1, -// (scan_y2 - scan_y1) / y_steps, -// (scan_x2 - scan_x1) / x_steps, -// 0, -// 0); -// downsample->process_frame(downsampled_current, -// current_frame_arg, -// 1, -// 1, -// 1, -// 1, -// (scan_y2 - scan_y1) / y_steps, -// (scan_x2 - scan_x1) / x_steps, -// 0, -// 0); -// this->previous_frame = downsampled_previous; -// this->current_frame = downsampled_current; -// } - - - - - -// printf("MotionScan::scan_frame %d this->total_steps=%d\n", -// __LINE__, -// this->total_steps); - - - set_package_count(this->total_steps); - process_packages(); - -// Get least difference - int64_t min_difference = -1; - for(int i = 0; i < get_total_packages(); i++) - { - MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); -//printf("MotionScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", -//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2); - if(pkg->difference1 < min_difference || min_difference == -1) - { - min_difference = pkg->difference1; - x_result = pkg->search_x; - y_result = pkg->search_y; - x_result *= OVERSAMPLE; - y_result *= OVERSAMPLE; -//printf("MotionScan::scan_frame %d x_result=%d y_result=%d diff=%lld\n", -//__LINE__, block_x1 * OVERSAMPLE - x_result, block_y1 * OVERSAMPLE - y_result, pkg->difference1); - } - } - - -// If a new search is required, rescale results back to pixels. - if(this->total_steps >= total_pixels) - { -// Single pixel accuracy reached. Now do exhaustive subpixel search. - if(action_type == MotionScan::STABILIZE || - action_type == MotionScan::TRACK || - action_type == MotionScan::NOTHING) - { -//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result); - x_result /= OVERSAMPLE; - y_result /= OVERSAMPLE; - scan_w = 2; - scan_h = 2; - subpixel = 1; - } - else - { -// Fill in results and quit - dx_result = block_x1 * OVERSAMPLE - x_result; - dy_result = block_y1 * OVERSAMPLE - y_result; -//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, dx_result, dy_result); - break; - } - } - else -// Reduce scan area and try again - { - scan_w = (scan_x2 - scan_x1) / 2; - scan_h = (scan_y2 - scan_y1) / 2; - x_result /= OVERSAMPLE; - y_result /= OVERSAMPLE; - } - } - } - - dx_result *= -1; - dy_result *= -1; - } -//printf("MotionScan::scan_frame %d\n", __LINE__); - - - if(vertical_only) dx_result = 0; - if(horizontal_only) dy_result = 0; - - - -// Write results - if(tracking_type == MotionScan::SAVE) - { - char string[BCTEXTLEN]; - sprintf(string, - "%s%06d", - MOTION_FILE, - source_position); - FILE *output = fopen(string, "w"); - if(output) - { - fprintf(output, - "%d %d\n", - dx_result, - dy_result); - fclose(output); - } - else - { - printf("MotionScan::scan_frame %d: save coordinate failed", __LINE__); - } - } - -// printf("MotionScan::scan_frame %d dx=%.2f dy=%.2f\n", -// __LINE__, -// (float)this->dx_result / OVERSAMPLE, -// (float)this->dy_result / OVERSAMPLE); -} - - - - - - - - - - - - - - - - - -int64_t MotionScan::get_cache(int x, int y) -{ - int64_t result = -1; - cache_lock->lock("MotionScan::get_cache"); - for(int i = 0; i < cache.total; i++) - { - MotionScanCache *ptr = cache.values[i]; - if(ptr->x == x && ptr->y == y) - { - result = ptr->difference; - break; - } - } - cache_lock->unlock(); - return result; -} - -void MotionScan::put_cache(int x, int y, int64_t difference) -{ - MotionScanCache *ptr = new MotionScanCache(x, y, difference); - cache_lock->lock("MotionScan::put_cache"); - cache.append(ptr); - cache_lock->unlock(); -} - - - -#define ABS_DIFF(type, temp_type, multiplier, components) \ -{ \ - temp_type result_temp = 0; \ - for(int i = 0; i < h; i++) \ - { \ - type *prev_row = (type*)prev_ptr; \ - type *current_row = (type*)current_ptr; \ - for(int j = 0; j < w; j++) \ - { \ - for(int k = 0; k < 3; k++) \ - { \ - temp_type difference; \ - difference = *prev_row++ - *current_row++; \ - if(difference < 0) \ - result_temp -= difference; \ - else \ - result_temp += difference; \ - } \ - if(components == 4) \ - { \ - prev_row++; \ - current_row++; \ - } \ - } \ - prev_ptr += row_bytes; \ - current_ptr += row_bytes; \ - } \ - result = (int64_t)(result_temp * multiplier); \ -} - -int64_t MotionScan::abs_diff(unsigned char *prev_ptr, - unsigned char *current_ptr, - int row_bytes, - int w, - int h, - int color_model) -{ - int64_t result = 0; - switch(color_model) - { - case BC_RGB888: - ABS_DIFF(unsigned char, int64_t, 1, 3) - break; - case BC_RGBA8888: - ABS_DIFF(unsigned char, int64_t, 1, 4) - break; - case BC_RGB_FLOAT: - ABS_DIFF(float, double, 0x10000, 3) - break; - case BC_RGBA_FLOAT: - ABS_DIFF(float, double, 0x10000, 4) - break; - case BC_YUV888: - ABS_DIFF(unsigned char, int64_t, 1, 3) - break; - case BC_YUVA8888: - ABS_DIFF(unsigned char, int64_t, 1, 4) - break; - case BC_YUV161616: - ABS_DIFF(uint16_t, int64_t, 1, 3) - break; - case BC_YUVA16161616: - ABS_DIFF(uint16_t, int64_t, 1, 4) - break; - } - return result; -} - - - -#define ABS_DIFF_SUB(type, temp_type, multiplier, components) \ -{ \ - temp_type result_temp = 0; \ - temp_type y2_fraction = sub_y * 0x100 / OVERSAMPLE; \ - temp_type y1_fraction = 0x100 - y2_fraction; \ - temp_type x2_fraction = sub_x * 0x100 / OVERSAMPLE; \ - temp_type x1_fraction = 0x100 - x2_fraction; \ - for(int i = 0; i < h_sub; i++) \ - { \ - type *prev_row1 = (type*)prev_ptr; \ - type *prev_row2 = (type*)prev_ptr + components; \ - type *prev_row3 = (type*)(prev_ptr + row_bytes); \ - type *prev_row4 = (type*)(prev_ptr + row_bytes) + components; \ - type *current_row = (type*)current_ptr; \ - for(int j = 0; j < w_sub; j++) \ - { \ -/* Scan each component */ \ - for(int k = 0; k < 3; k++) \ - { \ - temp_type difference; \ - temp_type prev_value = \ - (*prev_row1++ * x1_fraction * y1_fraction + \ - *prev_row2++ * x2_fraction * y1_fraction + \ - *prev_row3++ * x1_fraction * y2_fraction + \ - *prev_row4++ * x2_fraction * y2_fraction) / \ - 0x100 / 0x100; \ - temp_type current_value = *current_row++; \ - difference = prev_value - current_value; \ - if(difference < 0) \ - result_temp -= difference; \ - else \ - result_temp += difference; \ - } \ - \ -/* skip alpha */ \ - if(components == 4) \ - { \ - prev_row1++; \ - prev_row2++; \ - prev_row3++; \ - prev_row4++; \ - current_row++; \ - } \ - } \ - prev_ptr += row_bytes; \ - current_ptr += row_bytes; \ - } \ - result = (int64_t)(result_temp * multiplier); \ -} - - - - -int64_t MotionScan::abs_diff_sub(unsigned char *prev_ptr, - unsigned char *current_ptr, - int row_bytes, - int w, - int h, - int color_model, - int sub_x, - int sub_y) -{ - int h_sub = h - 1; - int w_sub = w - 1; - int64_t result = 0; - - switch(color_model) - { - case BC_RGB888: - ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) - break; - case BC_RGBA8888: - ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) - break; - case BC_RGB_FLOAT: - ABS_DIFF_SUB(float, double, 0x10000, 3) - break; - case BC_RGBA_FLOAT: - ABS_DIFF_SUB(float, double, 0x10000, 4) - break; - case BC_YUV888: - ABS_DIFF_SUB(unsigned char, int64_t, 1, 3) - break; - case BC_YUVA8888: - ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) - break; - case BC_YUV161616: - ABS_DIFF_SUB(uint16_t, int64_t, 1, 3) - break; - case BC_YUVA16161616: - ABS_DIFF_SUB(uint16_t, int64_t, 1, 4) - break; - } - return result; -} - - - - - -MotionScanCache::MotionScanCache(int x, int y, int64_t difference) -{ - this->x = x; - this->y = y; - this->difference = difference; -} - - - -void MotionScan::clamp_scan(int w, - int h, - int *block_x1, - int *block_y1, - int *block_x2, - int *block_y2, - int *scan_x1, - int *scan_y1, - int *scan_x2, - int *scan_y2, - int use_absolute) -{ -// printf("MotionMain::clamp_scan 1 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", -// w, -// h, -// *block_x1, -// *block_y1, -// *block_x2, -// *block_y2, -// *scan_x1, -// *scan_y1, -// *scan_x2, -// *scan_y2, -// use_absolute); - - if(use_absolute) - { -// scan is always out of range before block. - if(*scan_x1 < 0) - { - int difference = -*scan_x1; - *block_x1 += difference; - *scan_x1 = 0; - } - - if(*scan_y1 < 0) - { - int difference = -*scan_y1; - *block_y1 += difference; - *scan_y1 = 0; - } - - if(*scan_x2 > w) - { - int difference = *scan_x2 - w; - *block_x2 -= difference; - *scan_x2 -= difference; - } - - if(*scan_y2 > h) - { - int difference = *scan_y2 - h; - *block_y2 -= difference; - *scan_y2 -= difference; - } - - CLAMP(*scan_x1, 0, w); - CLAMP(*scan_y1, 0, h); - CLAMP(*scan_x2, 0, w); - CLAMP(*scan_y2, 0, h); - } - else - { - if(*scan_x1 < 0) - { - int difference = -*scan_x1; - *block_x1 += difference; - *scan_x2 += difference; - *scan_x1 = 0; - } - - if(*scan_y1 < 0) - { - int difference = -*scan_y1; - *block_y1 += difference; - *scan_y2 += difference; - *scan_y1 = 0; - } - - if(*scan_x2 - *block_x1 + *block_x2 > w) - { - int difference = *scan_x2 - *block_x1 + *block_x2 - w; - *block_x2 -= difference; - } - - if(*scan_y2 - *block_y1 + *block_y2 > h) - { - int difference = *scan_y2 - *block_y1 + *block_y2 - h; - *block_y2 -= difference; - } - -// CLAMP(*scan_x1, 0, w - (*block_x2 - *block_x1)); -// CLAMP(*scan_y1, 0, h - (*block_y2 - *block_y1)); -// CLAMP(*scan_x2, 0, w - (*block_x2 - *block_x1)); -// CLAMP(*scan_y2, 0, h - (*block_y2 - *block_y1)); - } - -// Sanity checks which break the calculation but should never happen if the -// center of the block is inside the frame. - CLAMP(*block_x1, 0, w); - CLAMP(*block_x2, 0, w); - CLAMP(*block_y1, 0, h); - CLAMP(*block_y2, 0, h); - -// printf("MotionMain::clamp_scan 2 w=%d h=%d block=%d %d %d %d scan=%d %d %d %d absolute=%d\n", -// w, -// h, -// *block_x1, -// *block_y1, -// *block_x2, -// *block_y2, -// *scan_x1, -// *scan_y1, -// *scan_x2, -// *scan_y2, -// use_absolute); -} - - - diff --git a/cinelerra-5.1/plugins/motion.new/motionwindow.h b/cinelerra-5.1/plugins/motion.new/motionwindow.h deleted file mode 100644 index 02aa13b0..00000000 --- a/cinelerra-5.1/plugins/motion.new/motionwindow.h +++ /dev/null @@ -1,373 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 "guicast.h" -#include "motion.inc" - -class MasterLayer : public BC_PopupMenu -{ -public: - MasterLayer(MotionMain *plugin, MotionWindow *gui, int x, int y); - int handle_event(); - void create_objects(); - static int calculate_w(MotionWindow *gui); - static int from_text(char *text); - static char* to_text(int mode); - MotionMain *plugin; - MotionWindow *gui; -}; - -class ActionType : public BC_PopupMenu -{ -public: - ActionType(MotionMain *plugin, MotionWindow *gui, int x, int y); - int handle_event(); - void create_objects(); - static int calculate_w(MotionWindow *gui); - static int from_text(char *text); - static char* to_text(int mode); - MotionMain *plugin; - MotionWindow *gui; -}; - -class TrackingType : public BC_PopupMenu -{ -public: - TrackingType(MotionMain *plugin, MotionWindow *gui, int x, int y); - int handle_event(); - void create_objects(); - static int calculate_w(MotionWindow *gui); - static int from_text(char *text); - static char* to_text(int mode); - MotionMain *plugin; - MotionWindow *gui; -}; - -class TrackDirection : public BC_PopupMenu -{ -public: - TrackDirection(MotionMain *plugin, MotionWindow *gui, int x, int y); - int handle_event(); - void create_objects(); - static int calculate_w(MotionWindow *gui); - static void from_text(int *horizontal_only, int *vertical_only, char *text); - static char* to_text(int horizontal_only, int vertical_only); - MotionMain *plugin; - MotionWindow *gui; -}; - - -class TrackSingleFrame : public BC_Radial -{ -public: - TrackSingleFrame(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionMain *plugin; - MotionWindow *gui; -}; - -class TrackFrameNumber : public BC_TextBox -{ -public: - TrackFrameNumber(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionMain *plugin; - MotionWindow *gui; -}; - -class TrackPreviousFrame : public BC_Radial -{ -public: - TrackPreviousFrame(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionMain *plugin; - MotionWindow *gui; -}; - -class PreviousFrameSameBlock : public BC_Radial -{ -public: - PreviousFrameSameBlock(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionMain *plugin; - MotionWindow *gui; -}; - -class GlobalRange : public BC_IPot -{ -public: - GlobalRange(MotionMain *plugin, - int x, - int y, - int *value); - int handle_event(); - MotionMain *plugin; - int *value; -}; - -class RotationRange : public BC_IPot -{ -public: - RotationRange(MotionMain *plugin, - int x, - int y); - int handle_event(); - MotionMain *plugin; -}; - -class RotationCenter : public BC_IPot -{ -public: - RotationCenter(MotionMain *plugin, - int x, - int y); - int handle_event(); - MotionMain *plugin; -}; - -class BlockSize : public BC_IPot -{ -public: - BlockSize(MotionMain *plugin, - int x, - int y, - int *value); - int handle_event(); - MotionMain *plugin; - int *value; -}; - -class MotionBlockX : public BC_FPot -{ -public: - MotionBlockX(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionWindow *gui; - MotionMain *plugin; -}; - -class MotionBlockY : public BC_FPot -{ -public: - MotionBlockY(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionWindow *gui; - MotionMain *plugin; -}; - -class MotionBlockXText : public BC_TextBox -{ -public: - MotionBlockXText(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionWindow *gui; - MotionMain *plugin; -}; - -class MotionBlockYText : public BC_TextBox -{ -public: - MotionBlockYText(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionWindow *gui; - MotionMain *plugin; -}; - -class GlobalSearchPositions : public BC_PopupMenu -{ -public: - GlobalSearchPositions(MotionMain *plugin, - int x, - int y, - int w); - void create_objects(); - int handle_event(); - MotionMain *plugin; -}; - -class RotationSearchPositions : public BC_PopupMenu -{ -public: - RotationSearchPositions(MotionMain *plugin, - int x, - int y, - int w); - void create_objects(); - int handle_event(); - MotionMain *plugin; -}; - -class MotionMagnitude : public BC_IPot -{ -public: - MotionMagnitude(MotionMain *plugin, - int x, - int y); - int handle_event(); - MotionMain *plugin; -}; - -class MotionRMagnitude : public BC_IPot -{ -public: - MotionRMagnitude(MotionMain *plugin, - int x, - int y); - int handle_event(); - MotionMain *plugin; -}; - -class MotionReturnSpeed : public BC_IPot -{ -public: - MotionReturnSpeed(MotionMain *plugin, - int x, - int y); - int handle_event(); - MotionMain *plugin; -}; - - -class MotionRReturnSpeed : public BC_IPot -{ -public: - MotionRReturnSpeed(MotionMain *plugin, - int x, - int y); - int handle_event(); - MotionMain *plugin; -}; - - -class MotionDrawVectors : public BC_CheckBox -{ -public: - MotionDrawVectors(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionMain *plugin; - MotionWindow *gui; -}; - - -class MotionGlobal : public BC_CheckBox -{ -public: - MotionGlobal(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionWindow *gui; - MotionMain *plugin; -}; - -class MotionRotate : public BC_CheckBox -{ -public: - MotionRotate(MotionMain *plugin, - MotionWindow *gui, - int x, - int y); - int handle_event(); - MotionWindow *gui; - MotionMain *plugin; -}; - - - -class MotionWindow : public PluginClientWindow -{ -public: - MotionWindow(MotionMain *plugin); - ~MotionWindow(); - - void create_objects(); - void update_mode(); - char* get_radius_title(); - - GlobalRange *global_range_w; - GlobalRange *global_range_h; - RotationRange *rotation_range; - RotationCenter *rotation_center; - BlockSize *global_block_w; - BlockSize *global_block_h; - BlockSize *rotation_block_w; - BlockSize *rotation_block_h; - MotionBlockX *block_x; - MotionBlockY *block_y; - MotionBlockXText *block_x_text; - MotionBlockYText *block_y_text; - GlobalSearchPositions *global_search_positions; - RotationSearchPositions *rotation_search_positions; - MotionMagnitude *magnitude; - MotionRMagnitude *rotate_magnitude; - MotionReturnSpeed *return_speed; - MotionRReturnSpeed *rotate_return_speed; - ActionType *action_type; - MotionDrawVectors *vectors; - MotionGlobal *global; - MotionRotate *rotate; - TrackSingleFrame *track_single; - TrackFrameNumber *track_frame_number; - TrackPreviousFrame *track_previous; - PreviousFrameSameBlock *previous_same; - MasterLayer *master_layer; - TrackingType *tracking_type; - TrackDirection *track_direction; - - MotionMain *plugin; -}; - - - - - - - - - diff --git a/cinelerra-5.1/plugins/motion/motion.C b/cinelerra-5.1/plugins/motion/motion.C index 7d660b35..ed676803 100644 --- a/cinelerra-5.1/plugins/motion/motion.C +++ b/cinelerra-5.1/plugins/motion/motion.C @@ -1,7 +1,7 @@ /* * CINELERRA - * Copyright (C) 2016 Adam Williams + * Copyright (C) 2012 Adam Williams * * 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 @@ -33,7 +33,6 @@ #include "mutex.h" #include "overlayframe.h" #include "rotateframe.h" -#include "rotatescan.h" #include "transportque.h" @@ -42,6 +41,7 @@ REGISTER_PLUGIN(MotionMain) + #undef DEBUG // #ifndef DEBUG @@ -52,35 +52,48 @@ REGISTER_PLUGIN(MotionMain) MotionConfig::MotionConfig() { - global_range_w = 5; - global_range_h = 5; + global_range_w = 10; + global_range_h = 10; rotation_range = 5; rotation_center = 0; block_count = 1; - global_block_w = MIN_BLOCK; - global_block_h = MIN_BLOCK; + global_block_w = 50; // MIN_BLOCK; + global_block_h = 50; // MIN_BLOCK; // rotation_block_w = MIN_BLOCK; // rotation_block_h = MIN_BLOCK; block_x = 50; block_y = 50; -// global_positions = 256; -// rotate_positions = 4; - magnitude = 100; - rotate_magnitude = 90; - return_speed = 0; - rotate_return_speed = 0; - action_type = MotionScan::STABILIZE; -// global = 1; + global_positions = 256; + rotate_positions = 4; + magnitude = 25; + rotate_magnitude = 30; + return_speed = 8; + rotate_return_speed = 8; + action_type = MotionScan::STABILIZE_PIXEL; + global = 1; rotate = 1; - tracking_type = MotionScan::NO_CALCULATE; - draw_vectors = 1; - tracking_object = MotionScan::TRACK_SINGLE; + addtrackedframeoffset = 0; + tracking_type = MotionScan::CALCULATE; + draw_vectors = 0; + tracking_object = MotionScan::TRACK_PREVIOUS; track_frame = 0; bottom_is_master = 1; horizontal_only = 0; vertical_only = 0; } +void MotionConfig::set_cpus(int cpus) +{ + int gpos = 64, gpos_limit = 16 * cpus; + if( gpos_limit > 131072 ) gpos_limit = 131072; + while( gpos < gpos_limit ) gpos *= 2; + global_positions = gpos; + int rpos = 4, rpos_limit = cpus / 4; + if( rpos_limit > 32 ) gpos_limit = 32; + while( rpos < rpos_limit ) rpos *= 2; + rotate_positions = rpos; +} + void MotionConfig::boundaries() { CLAMP(global_range_w, MIN_RADIUS, MAX_RADIUS); @@ -101,8 +114,9 @@ int MotionConfig::equivalent(MotionConfig &that) rotation_range == that.rotation_range && rotation_center == that.rotation_center && action_type == that.action_type && -// global == that.global && + global == that.global && rotate == that.rotate && + addtrackedframeoffset == that.addtrackedframeoffset && draw_vectors == that.draw_vectors && block_count == that.block_count && global_block_w == that.global_block_w && @@ -111,8 +125,8 @@ int MotionConfig::equivalent(MotionConfig &that) // rotation_block_h == that.rotation_block_h && EQUIV(block_x, that.block_x) && EQUIV(block_y, that.block_y) && -// global_positions == that.global_positions && -// rotate_positions == that.rotate_positions && + global_positions == that.global_positions && + rotate_positions == that.rotate_positions && magnitude == that.magnitude && return_speed == that.return_speed && rotate_return_speed == that.rotate_return_speed && @@ -131,15 +145,16 @@ void MotionConfig::copy_from(MotionConfig &that) rotation_range = that.rotation_range; rotation_center = that.rotation_center; action_type = that.action_type; -// global = that.global; + global = that.global; rotate = that.rotate; + addtrackedframeoffset = that.addtrackedframeoffset; tracking_type = that.tracking_type; draw_vectors = that.draw_vectors; block_count = that.block_count; block_x = that.block_x; block_y = that.block_y; -// global_positions = that.global_positions; -// rotate_positions = that.rotate_positions; + global_positions = that.global_positions; + rotate_positions = that.rotate_positions; global_block_w = that.global_block_w; global_block_h = that.global_block_h; // rotation_block_w = that.rotation_block_w; @@ -170,13 +185,14 @@ void MotionConfig::interpolate(MotionConfig &prev, rotation_range = prev.rotation_range; rotation_center = prev.rotation_center; action_type = prev.action_type; -// global = prev.global; + global = prev.global; rotate = prev.rotate; + addtrackedframeoffset = prev.addtrackedframeoffset; tracking_type = prev.tracking_type; draw_vectors = prev.draw_vectors; block_count = prev.block_count; -// global_positions = prev.global_positions; -// rotate_positions = prev.rotate_positions; + global_positions = prev.global_positions; + rotate_positions = prev.rotate_positions; global_block_w = prev.global_block_w; global_block_h = prev.global_block_h; // rotation_block_w = prev.rotation_block_w; @@ -215,7 +231,7 @@ MotionMain::MotionMain(PluginServer *server) { engine = 0; rotate_engine = 0; -// motion_rotate = 0; + motion_rotate = 0; total_dx = 0; total_dy = 0; total_angle = 0; @@ -234,6 +250,8 @@ MotionMain::MotionMain(PluginServer *server) current_rotate_ref = 0; rotate_target_src = 0; rotate_target_dst = 0; + + config.set_cpus(get_project_smp() + 1); } MotionMain::~MotionMain() @@ -244,7 +262,7 @@ MotionMain::~MotionMain() delete [] search_area; delete temp_frame; delete rotate_engine; -// delete motion_rotate; + delete motion_rotate; delete prev_global_ref; @@ -277,11 +295,11 @@ void MotionMain::update_gui() { thread->window->lock_window("MotionMain::update_gui"); -// char string[BCTEXTLEN]; -// sprintf(string, "%d", config.global_positions); -// ((MotionWindow*)thread->window)->global_search_positions->set_text(string); -// sprintf(string, "%d", config.rotate_positions); -// ((MotionWindow*)thread->window)->rotation_search_positions->set_text(string); + char string[BCTEXTLEN]; + sprintf(string, "%d", config.global_positions); + ((MotionWindow*)thread->window)->global_search_positions->set_text(string); + sprintf(string, "%d", config.rotate_positions); + ((MotionWindow*)thread->window)->rotation_search_positions->set_text(string); ((MotionWindow*)thread->window)->global_block_w->update(config.global_block_w); ((MotionWindow*)thread->window)->global_block_h->update(config.global_block_h); @@ -336,8 +354,8 @@ void MotionMain::save_data(KeyFrame *keyframe) output.tag.set_title("MOTION"); output.tag.set_property("BLOCK_COUNT", config.block_count); -// output.tag.set_property("GLOBAL_POSITIONS", config.global_positions); -// output.tag.set_property("ROTATE_POSITIONS", config.rotate_positions); + output.tag.set_property("GLOBAL_POSITIONS", config.global_positions); + output.tag.set_property("ROTATE_POSITIONS", config.rotate_positions); output.tag.set_property("GLOBAL_BLOCK_W", config.global_block_w); output.tag.set_property("GLOBAL_BLOCK_H", config.global_block_h); // output.tag.set_property("ROTATION_BLOCK_W", config.rotation_block_w); @@ -353,8 +371,9 @@ void MotionMain::save_data(KeyFrame *keyframe) output.tag.set_property("ROTATE_MAGNITUDE", config.rotate_magnitude); output.tag.set_property("ROTATE_RETURN_SPEED", config.rotate_return_speed); output.tag.set_property("ACTION_TYPE", config.action_type); -// output.tag.set_property("GLOBAL", config.global); + output.tag.set_property("GLOBAL", config.global); output.tag.set_property("ROTATE", config.rotate); + output.tag.set_property("ADDTRACKEDFRAMEOFFSET", config.addtrackedframeoffset); output.tag.set_property("TRACKING_TYPE", config.tracking_type); output.tag.set_property("DRAW_VECTORS", config.draw_vectors); output.tag.set_property("TRACKING_OBJECT", config.tracking_object); @@ -385,8 +404,8 @@ void MotionMain::read_data(KeyFrame *keyframe) if(input.tag.title_is("MOTION")) { config.block_count = input.tag.get_property("BLOCK_COUNT", config.block_count); -// config.global_positions = input.tag.get_property("GLOBAL_POSITIONS", config.global_positions); -// config.rotate_positions = input.tag.get_property("ROTATE_POSITIONS", config.rotate_positions); + config.global_positions = input.tag.get_property("GLOBAL_POSITIONS", config.global_positions); + config.rotate_positions = input.tag.get_property("ROTATE_POSITIONS", config.rotate_positions); config.global_block_w = input.tag.get_property("GLOBAL_BLOCK_W", config.global_block_w); config.global_block_h = input.tag.get_property("GLOBAL_BLOCK_H", config.global_block_h); // config.rotation_block_w = input.tag.get_property("ROTATION_BLOCK_W", config.rotation_block_w); @@ -402,8 +421,9 @@ void MotionMain::read_data(KeyFrame *keyframe) config.rotate_magnitude = input.tag.get_property("ROTATE_MAGNITUDE", config.rotate_magnitude); config.rotate_return_speed = input.tag.get_property("ROTATE_RETURN_SPEED", config.rotate_return_speed); config.action_type = input.tag.get_property("ACTION_TYPE", config.action_type); -// config.global = input.tag.get_property("GLOBAL", config.global); + config.global = input.tag.get_property("GLOBAL", config.global); config.rotate = input.tag.get_property("ROTATE", config.rotate); + config.addtrackedframeoffset = input.tag.get_property("ADDTRACKEDFRAMEOFFSET", config.addtrackedframeoffset); config.tracking_type = input.tag.get_property("TRACKING_TYPE", config.tracking_type); config.draw_vectors = input.tag.get_property("DRAW_VECTORS", config.draw_vectors); config.tracking_object = input.tag.get_property("TRACKING_OBJECT", config.tracking_object); @@ -441,39 +461,30 @@ void MotionMain::allocate_temp(int w, int h, int color_model) void MotionMain::process_global() { - int w = current_global_ref->get_w(); - int h = current_global_ref->get_h(); - if(!engine) engine = new MotionScan(PluginClient::get_project_smp() + 1, PluginClient::get_project_smp() + 1); // Determine if frames changed -// printf("MotionMain::process_global %d block_y=%f total_dy=%d\n", -// __LINE__, config.block_y * h / 100, total_dy); engine->scan_frame(current_global_ref, prev_global_ref, - config.global_range_w * w / 100, - config.global_range_h * h / 100, - config.global_block_w * w / 100, - config.global_block_h * h / 100, - config.block_x * w / 100, - config.block_y * h / 100, + config.global_range_w, + config.global_range_h, + config.global_block_w, + config.global_block_h, + config.block_x, + config.block_y, config.tracking_object, config.tracking_type, config.action_type, config.horizontal_only, config.vertical_only, get_source_position(), + config.global_positions, total_dx, total_dy, 0, - 0, - 1, // do_motion - config.rotate, // do_rotate - config.rotation_center, - config.rotation_range); - + 0); current_dx = engine->dx_result; current_dy = engine->dy_result; @@ -485,8 +496,9 @@ void MotionMain::process_global() total_dy = (int64_t)total_dy * (100 - config.return_speed) / 100; total_dx += engine->dx_result; total_dy += engine->dy_result; -// printf("MotionMain::process_global %d total_dy=%d engine->dy_result=%d\n", -// __LINE__, total_dy, engine->dy_result); +// printf("MotionMain::process_global total_dx=%d engine->dx_result=%d\n", +// total_dx, +// engine->dx_result); } else // Make accumulation vector current @@ -498,27 +510,43 @@ void MotionMain::process_global() // Clamp accumulation vector if(config.magnitude < 100) { - //int block_w = (int64_t)config.global_block_w * w / 100; - //int block_h = (int64_t)config.global_block_h * h / 100; - int block_x_orig = (int64_t)(config.block_x * w / 100); + //int block_w = (int64_t)config.global_block_w * + // current_global_ref->get_w() / 100; + //int block_h = (int64_t)config.global_block_h * + // current_global_ref->get_h() / 100; + int block_x_orig = (int64_t)(config.block_x * + current_global_ref->get_w() / + 100); int block_y_orig = (int64_t)(config.block_y * - current_global_ref->get_h() / h / 100); + current_global_ref->get_h() / + 100); - int max_block_x = (int64_t)(w - block_x_orig) * - OVERSAMPLE * config.magnitude / 100; - int max_block_y = (int64_t)(h - block_y_orig) * - OVERSAMPLE * config.magnitude / 100; + int max_block_x = (int64_t)(current_global_ref->get_w() - block_x_orig) * + OVERSAMPLE * + config.magnitude / + 100; + int max_block_y = (int64_t)(current_global_ref->get_h() - block_y_orig) * + OVERSAMPLE * + config.magnitude / + 100; int min_block_x = (int64_t)-block_x_orig * - OVERSAMPLE * config.magnitude / 100; + OVERSAMPLE * + config.magnitude / + 100; int min_block_y = (int64_t)-block_y_orig * - OVERSAMPLE * config.magnitude / 100; + OVERSAMPLE * + config.magnitude / + 100; CLAMP(total_dx, min_block_x, max_block_x); CLAMP(total_dy, min_block_y, max_block_y); } -// printf("MotionMain::process_global %d total_dx=%d total_dy=%d\n", -// __LINE__, total_dx, total_dy); +#ifdef DEBUG +printf("MotionMain::process_global 2 total_dx=%.02f total_dy=%.02f\n", +(float)total_dx / OVERSAMPLE, +(float)total_dy / OVERSAMPLE); +#endif if(config.tracking_object != MotionScan::TRACK_SINGLE && !config.rotate) { @@ -547,6 +575,7 @@ void MotionMain::process_global() dx = -(int)(total_dx / OVERSAMPLE); dy = -(int)(total_dy / OVERSAMPLE); break; + break; case MotionScan::TRACK: interpolation = CUBIC_LINEAR; dx = (float)total_dx / OVERSAMPLE; @@ -588,11 +617,9 @@ void MotionMain::process_rotation() int block_x; int block_y; -// Always require global // Convert the previous global reference into the previous rotation reference. // Convert global target destination into rotation target source. -// if(config.global) - if(1) + if(config.global) { if(!overlayer) overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); @@ -657,17 +684,17 @@ void MotionMain::process_rotation() // Get rotation -// if(!motion_rotate) -// motion_rotate = new RotateScan(this, -// get_project_smp() + 1, -// get_project_smp() + 1); -// -// current_angle = motion_rotate->scan_frame(prev_rotate_ref, -// current_rotate_ref, -// block_x, -// block_y); - - current_angle = engine->dr_result; + if(!motion_rotate) + motion_rotate = new RotateScan(this, + get_project_smp() + 1, + get_project_smp() + 1); + + current_angle = motion_rotate->scan_frame(prev_rotate_ref, + current_rotate_ref, + block_x, + block_y); + + // Add current rotation to accumulation if(config.tracking_object != MotionScan::TRACK_SINGLE) @@ -683,13 +710,13 @@ void MotionMain::process_rotation() CLAMP(total_angle, -config.rotate_magnitude, config.rotate_magnitude); } -// if(!config.global) -// { + if(!config.global) + { // Transfer current reference frame to previous reference frame and update // counter. -// prev_rotate_ref->copy_from(current_rotate_ref); -// previous_frame_number = get_source_position(); -// } + prev_rotate_ref->copy_from(current_rotate_ref); + previous_frame_number = get_source_position(); + } } else { @@ -741,8 +768,7 @@ printf("MotionMain::process_rotation total_angle=%f\n", total_angle); case MotionScan::STABILIZE: case MotionScan::STABILIZE_PIXEL: -// if(config.global) - if(1) + if(config.global) { // Use origin of global stabilize operation // rotate_engine->set_pivot((int)(rotate_target_dst->get_w() * @@ -776,7 +802,6 @@ printf("MotionMain::process_rotation total_angle=%f\n", total_angle); } -printf("MotionMain::process_rotation angle=%f\n", angle); rotate_engine->rotate(rotate_target_dst, rotate_target_src, angle); // overlayer->overlay(rotate_target_dst, // prev_rotate_ref, @@ -898,7 +923,7 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po } -// if(!config.global && !config.rotate) skip_current = 1; + if(!config.global && !config.rotate) skip_current = 1; @@ -934,8 +959,7 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po // Get the global pointers. Here we walk through the sequence of events. -// if(config.global) - if(1) + if(config.global) { // Assume global only. Global reads previous frame and compares // with current frame to get the current translation. @@ -1048,14 +1072,13 @@ printf("MotionMain::process_buffer %d start_position=%lld\n", __LINE__, start_po -//PRINT_TRACE -//printf("skip_current=%d config.global=%d\n", skip_current, config.global); + if(!skip_current) { // Get position change from previous frame to current frame - /* if(config.global) */ process_global(); + if(config.global) process_global(); // Get rotation change from previous frame to current frame if(config.rotate) process_rotation(); //frame[target_layer]->copy_from(prev_rotate_ref); @@ -1119,9 +1142,7 @@ void MotionMain::draw_vectors(VFrame *frame) int search_x2, search_y2; -// always processing global -// if(config.global) - if(1) + if(config.global) { // Get vector // Start of vector is center of previous block. @@ -1438,3 +1459,439 @@ void MotionMain::draw_arrow(VFrame *frame, int x1, int y1, int x2, int y2) + + + + + + + + + +RotateScanPackage::RotateScanPackage() +{ +} + + +RotateScanUnit::RotateScanUnit(RotateScan *server, MotionMain *plugin) + : LoadClient(server) +{ + this->server = server; + this->plugin = plugin; + rotater = 0; + temp = 0; +} + +RotateScanUnit::~RotateScanUnit() +{ + delete rotater; + delete temp; +} + +void RotateScanUnit::process_package(LoadPackage *package) +{ + if(server->skip) return; + RotateScanPackage *pkg = (RotateScanPackage*)package; + + if((pkg->difference = server->get_cache(pkg->angle)) < 0) + { +//printf("RotateScanUnit::process_package %d\n", __LINE__); + int color_model = server->previous_frame->get_color_model(); + int pixel_size = BC_CModels::calculate_pixelsize(color_model); + int row_bytes = server->previous_frame->get_bytes_per_line(); + + if(!rotater) + rotater = new AffineEngine(1, 1); + if(!temp) temp = new VFrame(0, + -1, + server->previous_frame->get_w(), + server->previous_frame->get_h(), + color_model, + -1); +//printf("RotateScanUnit::process_package %d\n", __LINE__); + + +// Rotate original block size +// rotater->set_viewport(server->block_x1, +// server->block_y1, +// server->block_x2 - server->block_x1, +// server->block_y2 - server->block_y1); + rotater->set_in_viewport(server->block_x1, + server->block_y1, + server->block_x2 - server->block_x1, + server->block_y2 - server->block_y1); + rotater->set_out_viewport(server->block_x1, + server->block_y1, + server->block_x2 - server->block_x1, + server->block_y2 - server->block_y1); +// rotater->set_pivot(server->block_x, server->block_y); + rotater->set_in_pivot(server->block_x, server->block_y); + rotater->set_out_pivot(server->block_x, server->block_y); +//printf("RotateScanUnit::process_package %d\n", __LINE__); + rotater->rotate(temp, + server->previous_frame, + pkg->angle); + +// Scan reduced block size +//plugin->output_frame->copy_from(server->current_frame); +//plugin->output_frame->copy_from(temp); +// printf("RotateScanUnit::process_package %d %d %d %d %d\n", +// __LINE__, +// server->scan_x, +// server->scan_y, +// server->scan_w, +// server->scan_h); +// Clamp coordinates + int x1 = server->scan_x; + int y1 = server->scan_y; + int x2 = x1 + server->scan_w; + int y2 = y1 + server->scan_h; + x2 = MIN(temp->get_w(), x2); + y2 = MIN(temp->get_h(), y2); + x2 = MIN(server->current_frame->get_w(), x2); + y2 = MIN(server->current_frame->get_h(), y2); + x1 = MAX(0, x1); + y1 = MAX(0, y1); + + if(x2 > x1 && y2 > y1) + { + pkg->difference = MotionScan::abs_diff( + temp->get_rows()[y1] + x1 * pixel_size, + server->current_frame->get_rows()[y1] + x1 * pixel_size, + row_bytes, + x2 - x1, + y2 - y1, + color_model); +//printf("RotateScanUnit::process_package %d\n", __LINE__); + server->put_cache(pkg->angle, pkg->difference); + } +#if 0 + VFrame png(x2-x1, y2-y1, BC_RGB888, -1); + png.transfer_from(temp, 0, x1, y1, x2-x1, y2-y1); + char fn[64]; + sprintf(fn,"%s%f.png","/tmp/temp",pkg->angle); png.write_png(fn); + png.transfer_from(server->current_frame, 0, x1, y1, x2-x1, y2-y1); + sprintf(fn,"%s%f.png","/tmp/curr",pkg->angle); png.write_png(fn); +printf("RotateScanUnit::process_package 10 x=%d y=%d w=%d h=%d block_x=%d block_y=%d angle=%f scan_w=%d scan_h=%d diff=%jd\n", + server->block_x1, server->block_y1, server->block_x2 - server->block_x1, server->block_y2 - server->block_y1, + server->block_x, server->block_y, pkg->angle, server->scan_w, server->scan_h, pkg->difference); +#endif + } +} + + + + + + + + + + + + + + + + + + + + + + +RotateScan::RotateScan(MotionMain *plugin, + int total_clients, + int total_packages) + : LoadServer( +//1, 1 +total_clients, total_packages +) +{ + this->plugin = plugin; + cache_lock = new Mutex("RotateScan::cache_lock"); +} + + +RotateScan::~RotateScan() +{ + delete cache_lock; +} + +void RotateScan::init_packages() +{ + for(int i = 0; i < get_total_packages(); i++) + { + RotateScanPackage *pkg = (RotateScanPackage*)get_package(i); + pkg->angle = i * + (scan_angle2 - scan_angle1) / + (total_steps - 1) + + scan_angle1; + } +} + +LoadClient* RotateScan::new_client() +{ + return new RotateScanUnit(this, plugin); +} + +LoadPackage* RotateScan::new_package() +{ + return new RotateScanPackage; +} + + +float RotateScan::scan_frame(VFrame *previous_frame, + VFrame *current_frame, + int block_x, + int block_y) +{ + skip = 0; + this->block_x = block_x; + this->block_y = block_y; + +//printf("RotateScan::scan_frame %d\n", __LINE__); + switch(plugin->config.tracking_type) + { + case MotionScan::NO_CALCULATE: + result = plugin->config.rotation_center; + skip = 1; + break; + + case MotionScan::LOAD: + { + char string[BCTEXTLEN]; + sprintf(string, "%s%06jd", + ROTATION_FILE, plugin->get_source_position()); + FILE *input = fopen(string, "r"); + if(input) + { + fscanf(input, "%f", &result); + fclose(input); + skip = 1; + } + else + { + perror("RotateScan::scan_frame LOAD"); + } + break; + } + } + + + + + + + + + this->previous_frame = previous_frame; + this->current_frame = current_frame; + int w = current_frame->get_w(); + int h = current_frame->get_h(); + int block_w = w * plugin->config.global_block_w / 100; + int block_h = h * plugin->config.global_block_h / 100; + + if(this->block_x - block_w / 2 < 0) block_w = this->block_x * 2; + if(this->block_y - block_h / 2 < 0) block_h = this->block_y * 2; + if(this->block_x + block_w / 2 > w) block_w = (w - this->block_x) * 2; + if(this->block_y + block_h / 2 > h) block_h = (h - this->block_y) * 2; + + block_x1 = this->block_x - block_w / 2; + block_x2 = this->block_x + block_w / 2; + block_y1 = this->block_y - block_h / 2; + block_y2 = this->block_y + block_h / 2; + +// Calculate the maximum area available to scan after rotation. +// Must be calculated from the starting range because of cache. +// Get coords of rectangle after rotation. + double center_x = this->block_x; + double center_y = this->block_y; + double max_angle = plugin->config.rotation_range; + double base_angle1 = atan((float)block_h / block_w); + double base_angle2 = atan((float)block_w / block_h); + double target_angle1 = base_angle1 + max_angle * 2 * M_PI / 360; + double target_angle2 = base_angle2 + max_angle * 2 * M_PI / 360; + double radius = sqrt(block_w * block_w + block_h * block_h) / 2; + double x1 = center_x - cos(target_angle1) * radius; + double y1 = center_y - sin(target_angle1) * radius; + double x2 = center_x + sin(target_angle2) * radius; + double y2 = center_y - cos(target_angle2) * radius; + double x3 = center_x - sin(target_angle2) * radius; + double y3 = center_y + cos(target_angle2) * radius; + +// Track top edge to find greatest area. + double max_area1 = 0; + //double max_x1 = 0; + double max_y1 = 0; + for(double x = x1; x < x2; x++) + { + double y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); + if(x >= center_x && x < block_x2 && y >= block_y1 && y < center_y) + { + double area = fabs(x - center_x) * fabs(y - center_y); + if(area > max_area1) + { + max_area1 = area; + //max_x1 = x; + max_y1 = y; + } + } + } + +// Track left edge to find greatest area. + double max_area2 = 0; + double max_x2 = 0; + //double max_y2 = 0; + for(double y = y1; y < y3; y++) + { + double x = x1 + (x3 - x1) * (y - y1) / (y3 - y1); + if(x >= block_x1 && x < center_x && y >= block_y1 && y < center_y) + { + double area = fabs(x - center_x) * fabs(y - center_y); + if(area > max_area2) + { + max_area2 = area; + max_x2 = x; + //max_y2 = y; + } + } + } + + double max_x, max_y; + max_x = max_x2; + max_y = max_y1; + +// Get reduced scan coords + scan_w = (int)(fabs(max_x - center_x) * 2); + scan_h = (int)(fabs(max_y - center_y) * 2); + scan_x = (int)(center_x - scan_w / 2); + scan_y = (int)(center_y - scan_h / 2); +// printf("RotateScan::scan_frame center=%d,%d scan=%d,%d %dx%d\n", +// this->block_x, this->block_y, scan_x, scan_y, scan_w, scan_h); +// printf(" angle_range=%f block= %d,%d,%d,%d\n", max_angle, block_x1, block_y1, block_x2, block_y2); + +// Determine min angle from size of block + double angle1 = atan((double)block_h / block_w); + double angle2 = atan((double)(block_h - 1) / (block_w + 1)); + double min_angle = fabs(angle2 - angle1) / OVERSAMPLE; + min_angle = MAX(min_angle, MIN_ANGLE); + +//printf("RotateScan::scan_frame %d min_angle=%f\n", __LINE__, min_angle * 360 / 2 / M_PI); + + cache.remove_all_objects(); + + + if(!skip) + { + if(previous_frame->data_matches(current_frame)) + { +//printf("RotateScan::scan_frame: frames match. Skipping.\n"); + result = plugin->config.rotation_center; + skip = 1; + } + } + + if(!skip) + { +// Initial search range + float angle_range = max_angle; + result = plugin->config.rotation_center; + total_steps = plugin->config.rotate_positions; + + + while(angle_range >= min_angle * total_steps) + { + scan_angle1 = result - angle_range; + scan_angle2 = result + angle_range; + + + set_package_count(total_steps); +//set_package_count(1); + process_packages(); + + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + RotateScanPackage *pkg = (RotateScanPackage*)get_package(i); + if(pkg->difference < min_difference || min_difference == -1) + { + min_difference = pkg->difference; + result = pkg->angle; + } +//break; + } + + angle_range /= 2; + +//break; + } + } + +//printf("RotateScan::scan_frame %d\n", __LINE__); + + if(!skip && plugin->config.tracking_type == MotionScan::SAVE) + { + char string[BCTEXTLEN]; + sprintf(string, "%s%06jd", + ROTATION_FILE, plugin->get_source_position()); + FILE *output = fopen(string, "w"); + if(output) + { + fprintf(output, "%f\n", result); + fclose(output); + } + else + { + perror("RotateScan::scan_frame SAVE"); + } + } + +//printf("RotateScan::scan_frame %d angle=%f\n", __LINE__, result); + + + + return result; +} + +int64_t RotateScan::get_cache(float angle) +{ + int64_t result = -1; + cache_lock->lock("RotateScan::get_cache"); + for(int i = 0; i < cache.total; i++) + { + RotateScanCache *ptr = cache.values[i]; + if(fabs(ptr->angle - angle) <= MIN_ANGLE) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void RotateScan::put_cache(float angle, int64_t difference) +{ + RotateScanCache *ptr = new RotateScanCache(angle, difference); + cache_lock->lock("RotateScan::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + + + + + + + +RotateScanCache::RotateScanCache(float angle, int64_t difference) +{ + this->angle = angle; + this->difference = difference; +} + + + diff --git a/cinelerra-5.1/plugins/motion/motion.h b/cinelerra-5.1/plugins/motion/motion.h index 5b359f4b..e0011d75 100644 --- a/cinelerra-5.1/plugins/motion/motion.h +++ b/cinelerra-5.1/plugins/motion/motion.h @@ -1,7 +1,7 @@ /* * CINELERRA - * Copyright (C) 2016 Adam Williams + * Copyright (C) 2008 Adam Williams * * 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 @@ -35,11 +35,12 @@ #include "motionwindow.inc" #include "overlayframe.inc" #include "pluginvclient.h" -#include "rotatescan.inc" +#include "rotateframe.inc" #include "vframe.inc" class MotionMain; class MotionWindow; +class RotateScan; @@ -63,6 +64,7 @@ class MotionWindow; // Precision of rotation #define MIN_ANGLE 0.0001 +#define ROTATION_FILE "/tmp/r" class MotionConfig { @@ -77,6 +79,7 @@ public: int64_t next_frame, int64_t current_frame); void boundaries(); + void set_cpus(int cpus); int block_count; int global_range_w; @@ -96,8 +99,8 @@ public: // int rotation_block_w; // int rotation_block_h; // Number of search positions in each refinement of the log search -// int global_positions; -// int rotate_positions; + int global_positions; + int rotate_positions; // Block position in percentage 0 - 100 double block_x; double block_y; @@ -106,6 +109,7 @@ public: int vertical_only; int global; int rotate; + int addtrackedframeoffset; // Track or stabilize, single pixel, scan only, or nothing int action_type; // Recalculate, no calculate, save, or load coordinates from disk @@ -178,7 +182,7 @@ public: // It is moved to compensate for motion and copied to the previous_frame. VFrame *temp_frame; MotionScan *engine; -// RotateScan *motion_rotate; + RotateScan *motion_rotate; OverlayFrame *overlayer; AffineEngine *rotate_engine; @@ -244,6 +248,110 @@ public: + + + + + + + + + + + + + +class RotateScanPackage : public LoadPackage +{ +public: + RotateScanPackage(); + float angle; + int64_t difference; +}; + +class RotateScanCache +{ +public: + RotateScanCache(float angle, int64_t difference); + float angle; + int64_t difference; +}; + +class RotateScanUnit : public LoadClient +{ +public: + RotateScanUnit(RotateScan *server, MotionMain *plugin); + ~RotateScanUnit(); + + void process_package(LoadPackage *package); + + RotateScan *server; + MotionMain *plugin; + AffineEngine *rotater; + VFrame *temp; +}; + +class RotateScan : public LoadServer +{ +public: + RotateScan(MotionMain *plugin, + int total_clients, + int total_packages); + ~RotateScan(); + + friend class RotateScanUnit; + + void init_packages(); + LoadClient* new_client(); + LoadPackage* new_package(); + +// Invoke the motion engine for a search +// Frame before rotation + float scan_frame(VFrame *previous_frame, +// Frame after rotation + VFrame *current_frame, +// Pivot + int block_x, + int block_y); + int64_t get_cache(float angle); + void put_cache(float angle, int64_t difference); + + +// Angle result + float result; + +private: + VFrame *previous_frame; +// Frame after motion + VFrame *current_frame; + + MotionMain *plugin; + int skip; + +// Pivot + int block_x; + int block_y; +// Block to rotate + int block_x1; + int block_x2; + int block_y1; + int block_y2; +// Area to compare + int scan_x; + int scan_y; + int scan_w; + int scan_h; +// Range of angles to compare + float scan_angle1, scan_angle2; + int total_steps; + + ArrayList cache; + Mutex *cache_lock; +}; + + + + #endif diff --git a/cinelerra-5.1/plugins/motion/motion.inc b/cinelerra-5.1/plugins/motion/motion.inc index cf71a2a4..01c35947 100644 --- a/cinelerra-5.1/plugins/motion/motion.inc +++ b/cinelerra-5.1/plugins/motion/motion.inc @@ -2,21 +2,21 @@ /* * CINELERRA * Copyright (C) 2008 Adam Williams - * + * * 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 - * + * */ #ifndef MOTION_INC diff --git a/cinelerra-5.1/plugins/motion/motionscan.C b/cinelerra-5.1/plugins/motion/motionscan.C index 67e8460e..b1a533ef 100644 --- a/cinelerra-5.1/plugins/motion/motionscan.C +++ b/cinelerra-5.1/plugins/motion/motionscan.C @@ -1,46 +1,38 @@ /* * CINELERRA - * Copyright (C) 2016 Adam Williams - * + * Copyright (C) 2012 Adam Williams + * * 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 "affine.h" -#include "bcsignals.h" #include "clip.h" +//#include "../downsample/downsampleengine.h" +//#include "motion.h" #include "motionscan.h" #include "mutex.h" #include "vframe.h" - #include -#include -#include // The module which does the actual scanning -// starting level of detail -#define STARTING_DOWNSAMPLE 16 -// minimum size in each level of detail -#define MIN_DOWNSAMPLED_SIZE 16 -// minimum scan range -#define MIN_DOWNSAMPLED_SCAN 4 -// scan range for subpixel mode -#define SUBPIXEL_RANGE 4 + + + MotionScanPackage::MotionScanPackage() : LoadPackage() @@ -57,124 +49,116 @@ MotionScanUnit::MotionScanUnit(MotionScan *server) : LoadClient(server) { this->server = server; + cache_lock = new Mutex("MotionScanUnit::cache_lock"); } MotionScanUnit::~MotionScanUnit() { + delete cache_lock; } -void MotionScanUnit::single_pixel(MotionScanPackage *pkg) + +void MotionScanUnit::process_package(LoadPackage *package) { + MotionScanPackage *pkg = (MotionScanPackage*)package; //int w = server->current_frame->get_w(); //int h = server->current_frame->get_h(); int color_model = server->current_frame->get_color_model(); int pixel_size = BC_CModels::calculate_pixelsize(color_model); int row_bytes = server->current_frame->get_bytes_per_line(); -// printf("MotionScanUnit::process_package %d search_x=%d search_y=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d x_steps=%d y_steps=%d\n", -// __LINE__, -// pkg->search_x, -// pkg->search_y, -// pkg->scan_x1, -// pkg->scan_y1, -// pkg->scan_x2, -// pkg->scan_y2, -// server->x_steps, -// server->y_steps); -// Pointers to first pixel in each block - unsigned char *prev_ptr = server->previous_frame->get_rows()[ - pkg->search_y] + - pkg->search_x * pixel_size; - unsigned char *current_ptr = 0; - if(server->do_rotate) - { - current_ptr = server->rotated_current[pkg->angle_step]->get_rows()[ - pkg->block_y1] + - pkg->block_x1 * pixel_size; - } - else - { - current_ptr = server->current_frame->get_rows()[ - pkg->block_y1] + - pkg->block_x1 * pixel_size; - } -// Scan block - pkg->difference1 = MotionScan::abs_diff(prev_ptr, - current_ptr, - row_bytes, - pkg->block_x2 - pkg->block_x1, - pkg->block_y2 - pkg->block_y1, - color_model); - -// printf("MotionScanUnit::process_package %d angle_step=%d diff=%d\n", -// __LINE__, -// pkg->angle_step, -// pkg->difference1); -// printf("MotionScanUnit::process_package %d search_x=%d search_y=%d diff=%lld\n", -// __LINE__, server->block_x1 - pkg->search_x, server->block_y1 - pkg->search_y, pkg->difference1); -} -void MotionScanUnit::subpixel(MotionScanPackage *pkg) -{ -//PRINT_TRACE - //int w = server->current_frame->get_w(); - //int h = server->current_frame->get_h(); - int color_model = server->current_frame->get_color_model(); - int pixel_size = BC_CModels::calculate_pixelsize(color_model); - int row_bytes = server->current_frame->get_bytes_per_line(); - unsigned char *prev_ptr = server->previous_frame->get_rows()[ - pkg->search_y] + - pkg->search_x * pixel_size; -// neglect rotation - unsigned char *current_ptr = server->current_frame->get_rows()[ - pkg->block_y1] + - pkg->block_x1 * pixel_size; -// With subpixel, there are two ways to compare each position, one by shifting -// the previous frame and two by shifting the current frame. - pkg->difference1 = MotionScan::abs_diff_sub(prev_ptr, - current_ptr, - row_bytes, - pkg->block_x2 - pkg->block_x1, - pkg->block_y2 - pkg->block_y1, - color_model, - pkg->sub_x, - pkg->sub_y); - pkg->difference2 = MotionScan::abs_diff_sub(current_ptr, - prev_ptr, - row_bytes, - pkg->block_x2 - pkg->block_x1, - pkg->block_y2 - pkg->block_y1, - color_model, - pkg->sub_x, - pkg->sub_y); -// printf("MotionScanUnit::process_package sub_x=%d sub_y=%d search_x=%d search_y=%d diff1=%lld diff2=%lld\n", -// pkg->sub_x, -// pkg->sub_y, -// pkg->search_x, -// pkg->search_y, -// pkg->difference1, -// pkg->difference2); -} -void MotionScanUnit::process_package(LoadPackage *package) -{ - MotionScanPackage *pkg = (MotionScanPackage*)package; + + + // Single pixel if(!server->subpixel) { - single_pixel(pkg); +// Try cache + pkg->difference1 = server->get_cache(pkg->search_x, pkg->search_y); + if(pkg->difference1 < 0) + { +//printf("MotionScanUnit::process_package 1 search_x=%d search_y=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d x_steps=%d y_steps=%d\n", +//pkg->search_x, pkg->search_y, pkg->scan_x1, pkg->scan_y1, pkg->scan_x2, pkg->scan_y2, server->x_steps, server->y_steps); +// Pointers to first pixel in each block + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + pkg->search_y] + + pkg->search_x * pixel_size; + unsigned char *current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; + +// Scan block + pkg->difference1 = MotionScan::abs_diff(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model); + +// printf("MotionScanUnit::process_package %d search_x=%d search_y=%d diff=%lld\n", +// __LINE__, server->block_x1 - pkg->search_x, server->block_y1 - pkg->search_y, pkg->difference1); + server->put_cache(pkg->search_x, pkg->search_y, pkg->difference1); + } } + + + + + + + else + + + + + + + + // Sub pixel { - subpixel(pkg); + unsigned char *prev_ptr = server->previous_frame->get_rows()[ + pkg->search_y] + + pkg->search_x * pixel_size; + unsigned char *current_ptr = server->current_frame->get_rows()[ + pkg->block_y1] + + pkg->block_x1 * pixel_size; + +// With subpixel, there are two ways to compare each position, one by shifting +// the previous frame and two by shifting the current frame. + pkg->difference1 = MotionScan::abs_diff_sub(prev_ptr, + current_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + pkg->sub_x, + pkg->sub_y); + pkg->difference2 = MotionScan::abs_diff_sub(current_ptr, + prev_ptr, + row_bytes, + pkg->block_x2 - pkg->block_x1, + pkg->block_y2 - pkg->block_y1, + color_model, + pkg->sub_x, + pkg->sub_y); +// printf("MotionScanUnit::process_package sub_x=%d sub_y=%d search_x=%d search_y=%d diff1=%lld diff2=%lld\n", +// sub_x, +// sub_y, +// search_x, +// search_y, +// pkg->difference1, +// pkg->difference2); } @@ -191,6 +175,33 @@ void MotionScanUnit::process_package(LoadPackage *package) +int64_t MotionScanUnit::get_cache(int x, int y) +{ + int64_t result = -1; + cache_lock->lock("MotionScanUnit::get_cache"); + for(int i = 0; i < cache.total; i++) + { + MotionScanCache *ptr = cache.values[i]; + if(ptr->x == x && ptr->y == y) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void MotionScanUnit::put_cache(int x, int y, int64_t difference) +{ + MotionScanCache *ptr = new MotionScanCache(x, y, difference); + cache_lock->lock("MotionScanUnit::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + + + @@ -202,880 +213,135 @@ void MotionScanUnit::process_package(LoadPackage *package) MotionScan::MotionScan(int total_clients, int total_packages) : LoadServer( -// DEBUG -//1, 1 -total_clients, total_packages +//1, 1 +total_clients, total_packages ) { test_match = 1; + cache_lock = new Mutex("MotionScan::cache_lock"); downsampled_previous = 0; downsampled_current = 0; - rotated_current = 0; - rotater = 0; +// downsample = 0; } MotionScan::~MotionScan() { + delete cache_lock; delete downsampled_previous; delete downsampled_current; - if(rotated_current) - { - for(int i = 0; i < total_rotated; i++) - { - delete rotated_current[i]; - } - - delete [] rotated_current; - } - delete rotater; +// delete downsample; } void MotionScan::init_packages() { // Set package coords -// Total range of positions to scan with downsampling - int downsampled_scan_x1 = scan_x1 / current_downsample; - //int downsampled_scan_x2 = scan_x2 / current_downsample; - int downsampled_scan_y1 = scan_y1 / current_downsample; - //int downsampled_scan_y2 = scan_y2 / current_downsample; - int downsampled_block_x1 = block_x1 / current_downsample; - int downsampled_block_x2 = block_x2 / current_downsample; - int downsampled_block_y1 = block_y1 / current_downsample; - int downsampled_block_y2 = block_y2 / current_downsample; - - //printf("MotionScan::init_packages %d %d\n", __LINE__, get_total_packages()); -// printf("MotionScan::init_packages %d current_downsample=%d scan_x1=%d scan_x2=%d block_x1=%d block_x2=%d\n", -// __LINE__, -// current_downsample, -// downsampled_scan_x1, -// downsampled_scan_x2, -// downsampled_block_x1, -// downsampled_block_x2); -// if(current_downsample == 8 && downsampled_scan_x1 == 47) -// { -// downsampled_previous->write_png("/tmp/previous"); -// downsampled_current->write_png("/tmp/current"); -// } - for(int i = 0; i < get_total_packages(); i++) { MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); - pkg->block_x1 = downsampled_block_x1; - pkg->block_x2 = downsampled_block_x2; - pkg->block_y1 = downsampled_block_y1; - pkg->block_y2 = downsampled_block_y2; + pkg->block_x1 = block_x1; + pkg->block_x2 = block_x2; + pkg->block_y1 = block_y1; + pkg->block_y2 = block_y2; + pkg->scan_x1 = scan_x1; + pkg->scan_x2 = scan_x2; + pkg->scan_y1 = scan_y1; + pkg->scan_y2 = scan_y2; + pkg->step = i; pkg->difference1 = 0; pkg->difference2 = 0; pkg->dx = 0; pkg->dy = 0; pkg->valid = 1; - pkg->angle_step = 0; - + if(!subpixel) { - if(rotation_pass) - { - pkg->search_x = scan_x1 / current_downsample; - pkg->search_y = scan_y1 / current_downsample; - pkg->angle_step = i; - } - else - { - - int current_x_step = (i % x_steps); - int current_y_step = (i / x_steps); - - //printf("MotionScan::init_packages %d i=%d x_step=%d y_step=%d angle_step=%d\n", - //__LINE__, i, current_x_step, current_y_step, current_angle_step); - pkg->search_x = downsampled_scan_x1 + current_x_step * - (scan_x2 - scan_x1) / current_downsample / x_steps; - pkg->search_y = downsampled_scan_y1 + current_y_step * - (scan_y2 - scan_y1) / current_downsample / y_steps; - - if(do_rotate) - { - pkg->angle_step = angle_steps / 2; - } - else - { - pkg->angle_step = 0; - } - } - + pkg->search_x = pkg->scan_x1 + (pkg->step % x_steps) * + (scan_x2 - scan_x1) / x_steps; + pkg->search_y = pkg->scan_y1 + (pkg->step / x_steps) * + (scan_y2 - scan_y1) / y_steps; pkg->sub_x = 0; pkg->sub_y = 0; } else { - pkg->sub_x = i % (OVERSAMPLE * SUBPIXEL_RANGE); - pkg->sub_y = i / (OVERSAMPLE * SUBPIXEL_RANGE); - -// if(horizontal_only) -// { -// pkg->sub_y = 0; -// } -// -// if(vertical_only) -// { -// pkg->sub_x = 0; -// } - - pkg->search_x = scan_x1 + pkg->sub_x / OVERSAMPLE + 1; - pkg->search_y = scan_y1 + pkg->sub_y / OVERSAMPLE + 1; - pkg->sub_x %= OVERSAMPLE; - pkg->sub_y %= OVERSAMPLE; - - - -// printf("MotionScan::init_packages %d i=%d search_x=%d search_y=%d sub_x=%d sub_y=%d\n", -// __LINE__, -// i, -// pkg->search_x, -// pkg->search_y, -// pkg->sub_x, -// pkg->sub_y); - } - -// printf("MotionScan::init_packages %d %d,%d %d,%d %d,%d\n", -// __LINE__, -// scan_x1, -// scan_x2, -// scan_y1, -// scan_y2, -// pkg->search_x, -// pkg->search_y); - } -} - -LoadClient* MotionScan::new_client() -{ - return new MotionScanUnit(this); -} - -LoadPackage* MotionScan::new_package() -{ - return new MotionScanPackage; -} - - -void MotionScan::set_test_match(int value) -{ - this->test_match = value; -} - - - - -#define DOWNSAMPLE(type, temp_type, components, max) \ -{ \ - temp_type r; \ - temp_type g; \ - temp_type b; \ - temp_type a; \ - type **in_rows = (type**)src->get_rows(); \ - type **out_rows = (type**)dst->get_rows(); \ - \ - for(int i = 0; i < h; i += downsample) \ - { \ - int y1 = MAX(i, 0); \ - int y2 = MIN(i + downsample, h); \ - \ - \ - for(int j = 0; \ - j < w; \ - j += downsample) \ - { \ - int x1 = MAX(j, 0); \ - int x2 = MIN(j + downsample, w); \ - \ - temp_type scale = (x2 - x1) * (y2 - y1); \ - if(x2 > x1 && y2 > y1) \ - { \ - \ -/* Read in values */ \ - r = 0; \ - g = 0; \ - b = 0; \ - if(components == 4) a = 0; \ - \ - for(int k = y1; k < y2; k++) \ - { \ - type *row = in_rows[k] + x1 * components; \ - for(int l = x1; l < x2; l++) \ - { \ - r += *row++; \ - g += *row++; \ - b += *row++; \ - if(components == 4) a += *row++; \ - } \ - } \ - \ -/* Write average */ \ - r /= scale; \ - g /= scale; \ - b /= scale; \ - if(components == 4) a /= scale; \ - \ - type *row = out_rows[y1 / downsample] + \ - x1 / downsample * components; \ - *row++ = r; \ - *row++ = g; \ - *row++ = b; \ - if(components == 4) *row++ = a; \ - } \ - } \ -/*printf("DOWNSAMPLE 3 %d\n", i);*/ \ - } \ -} - - - - -void MotionScan::downsample_frame(VFrame *dst, - VFrame *src, - int downsample) -{ - int h = src->get_h(); - int w = src->get_w(); - -//PRINT_TRACE -//printf("downsample=%d w=%d h=%d dst=%d %d\n", downsample, w, h, dst->get_w(), dst->get_h()); - switch(src->get_color_model()) - { - case BC_RGB888: - DOWNSAMPLE(uint8_t, int64_t, 3, 0xff) - break; - case BC_RGB_FLOAT: - DOWNSAMPLE(float, float, 3, 1.0) - break; - case BC_RGBA8888: - DOWNSAMPLE(uint8_t, int64_t, 4, 0xff) - break; - case BC_RGBA_FLOAT: - DOWNSAMPLE(float, float, 4, 1.0) - break; - case BC_YUV888: - DOWNSAMPLE(uint8_t, int64_t, 3, 0xff) - break; - case BC_YUVA8888: - DOWNSAMPLE(uint8_t, int64_t, 4, 0xff) - break; - } -//PRINT_TRACE -} + pkg->sub_x = pkg->step % (OVERSAMPLE * 2); + pkg->sub_y = pkg->step / (OVERSAMPLE * 2); -double MotionScan::step_to_angle(int step, double center) -{ - if(step < angle_steps / 2) - { - return center - angle_step * (angle_steps / 2 - step); - } - else - if(step > angle_steps / 2) - { - return center + angle_step * (step - angle_steps / 2); - } - else - { - return center; - } -} - -#ifdef STDDEV_TEST -static int compare(const void *p1, const void *p2) -{ - double value1 = *(double*)p1; - double value2 = *(double*)p2; - -//printf("compare %d value1=%f value2=%f\n", __LINE__, value1, value2); - return value1 > value2; -} -#endif - -// reject vectors based on content. It's the reason Goog can't stabilize timelapses. -//#define STDDEV_TEST - -// pixel accurate motion search -void MotionScan::pixel_search(int &x_result, int &y_result, double &r_result) -{ -// reduce level of detail until enough steps - while(current_downsample > 1 && - ((block_x2 - block_x1) / current_downsample < MIN_DOWNSAMPLED_SIZE || - (block_y2 - block_y1) / current_downsample < MIN_DOWNSAMPLED_SIZE - || - (scan_x2 - scan_x1) / current_downsample < MIN_DOWNSAMPLED_SCAN || - (scan_y2 - scan_y1) / current_downsample < MIN_DOWNSAMPLED_SCAN - )) - { - current_downsample /= 2; - } - - - -// create downsampled images. -// Need to keep entire frame to search for rotation. - int downsampled_prev_w = previous_frame_arg->get_w() / current_downsample; - int downsampled_prev_h = previous_frame_arg->get_h() / current_downsample; - int downsampled_current_w = current_frame_arg->get_w() / current_downsample; - int downsampled_current_h = current_frame_arg->get_h() / current_downsample; - -// printf("MotionScan::pixel_search %d current_downsample=%d current_frame_arg->get_w()=%d downsampled_current_w=%d\n", -// __LINE__, -// current_downsample, -// current_frame_arg->get_w(), -// downsampled_current_w); - - x_steps = (scan_x2 - scan_x1) / current_downsample; - y_steps = (scan_y2 - scan_y1) / current_downsample; - -// in rads - double test_angle1 = atan2((double)downsampled_current_h / 2 - 1, (double)downsampled_current_w / 2); - double test_angle2 = atan2((double)downsampled_current_h / 2, (double)downsampled_current_w / 2 - 1); - -// in deg - angle_step = 360.0f * fabs(test_angle1 - test_angle2) / 2 / M_PI; - -// printf("MotionScan::pixel_search %d test_angle1=%f test_angle2=%f angle_step=%f\n", -// __LINE__, -// 360.0f * test_angle1 / 2 / M_PI, -// 360.0f * test_angle2 / 2 / M_PI, -// angle_step); - - - if(do_rotate && angle_step < rotation_range) - { - angle_steps = 1 + (int)((scan_angle2 - scan_angle1) / angle_step + 0.5); - } - else - { - angle_steps = 1; - } - - - if(current_downsample > 1) - { - if(!downsampled_previous || - downsampled_previous->get_w() != downsampled_prev_w || - downsampled_previous->get_h() != downsampled_prev_h) - { - delete downsampled_previous; - downsampled_previous = new VFrame(); - downsampled_previous->set_use_shm(0); - downsampled_previous->reallocate(0, - -1, - 0, - 0, - 0, - downsampled_prev_w + 1, - downsampled_prev_h + 1, - previous_frame_arg->get_color_model(), - -1); - } - - if(!downsampled_current || - downsampled_current->get_w() != downsampled_current_w || - downsampled_current->get_h() != downsampled_current_h) - { - delete downsampled_current; - downsampled_current = new VFrame(); - downsampled_current->set_use_shm(0); - downsampled_current->reallocate(0, - -1, - 0, - 0, - 0, - downsampled_current_w + 1, - downsampled_current_h + 1, - current_frame_arg->get_color_model(), - -1); - } - - - downsample_frame(downsampled_previous, - previous_frame_arg, - current_downsample); - downsample_frame(downsampled_current, - current_frame_arg, - current_downsample); - previous_frame = downsampled_previous; - current_frame = downsampled_current; - - } - else - { - previous_frame = previous_frame_arg; - current_frame = current_frame_arg; - } - - - -// printf("MotionScan::pixel_search %d x_steps=%d y_steps=%d angle_steps=%d total_steps=%d\n", -// __LINE__, -// x_steps, -// y_steps, -// angle_steps, -// total_steps); - - - -// test variance of constant macroblock - int color_model = current_frame->get_color_model(); - int pixel_size = BC_CModels::calculate_pixelsize(color_model); - int row_bytes = current_frame->get_bytes_per_line(); - int block_w = block_x2 - block_x1; - int block_h = block_y2 - block_y1; - - unsigned char *current_ptr = - current_frame->get_rows()[block_y1 / current_downsample] + - (block_x1 / current_downsample) * pixel_size; - unsigned char *previous_ptr = - previous_frame->get_rows()[scan_y1 / current_downsample] + - (scan_x1 / current_downsample) * pixel_size; - - - -// test detail in prev & current frame - double range1 = calculate_range(current_ptr, - row_bytes, - block_w / current_downsample, - block_h / current_downsample, - color_model); - - if(range1 < 1) - { -printf("MotionScan::pixel_search %d range fail range1=%f\n", __LINE__, range1); - failed = 1; - return; - } - - double range2 = calculate_range(previous_ptr, - row_bytes, - block_w / current_downsample, - block_h / current_downsample, - color_model); - - if(range2 < 1) - { -printf("MotionScan::pixel_search %d range fail range2=%f\n", __LINE__, range2); - failed = 1; - return; - } - - -// create rotated images - if(rotated_current && - (total_rotated != angle_steps || - rotated_current[0]->get_w() != downsampled_current_w || - rotated_current[0]->get_h() != downsampled_current_h)) - { - for(int i = 0; i < total_rotated; i++) - { - delete rotated_current[i]; - } - - delete [] rotated_current; - rotated_current = 0; - total_rotated = 0; - } - - if(do_rotate) - { - total_rotated = angle_steps; - - - if(!rotated_current) - { - rotated_current = new VFrame*[total_rotated]; - bzero(rotated_current, sizeof(VFrame*) * total_rotated); - } - -// printf("MotionScan::pixel_search %d total_rotated=%d w=%d h=%d block_w=%d block_h=%d\n", -// __LINE__, -// total_rotated, -// downsampled_current_w, -// downsampled_current_h, -// (block_x2 - block_x1) / current_downsample, -// (block_y2 - block_y1) / current_downsample); - for(int i = 0; i < angle_steps; i++) - { - -// printf("MotionScan::pixel_search %d w=%d h=%d x=%d y=%d angle=%f\n", -// __LINE__, -// downsampled_current_w, -// downsampled_current_h, -// (block_x1 + block_x2) / 2 / current_downsample, -// (block_y1 + block_y2) / 2 / current_downsample, -// step_to_angle(i, r_result)); - -// printf("MotionScan::pixel_search %d i=%d rotated_current[i]=%p\n", -// __LINE__, -// i, -// rotated_current[i]); - if(!rotated_current[i]) + if(horizontal_only) { - rotated_current[i] = new VFrame(); - rotated_current[i]->set_use_shm(0); - rotated_current[i]->reallocate(0, - -1, - 0, - 0, - 0, - downsampled_current_w + 1, - downsampled_current_h + 1, - current_frame_arg->get_color_model(), - -1); -//printf("MotionScan::pixel_search %d\n", __LINE__); + pkg->sub_y = 0; } - - if(!rotater) + if(vertical_only) { - rotater = new AffineEngine(get_total_clients(), - get_total_clients()); + pkg->sub_x = 0; } -// get smallest viewport size required for the angle - double diag = hypot((block_x2 - block_x1) / current_downsample, - (block_y2 - block_y1) / current_downsample); - double angle1 = atan2(block_y2 - block_y1, block_x2 - block_x1) + - TO_RAD(step_to_angle(i, r_result)); - double angle2 = -atan2(block_y2 - block_y1, block_x2 - block_x1) + - TO_RAD(step_to_angle(i, r_result)); - double max_horiz = MAX(abs(diag * cos(angle1)), abs(diag * cos(angle2))); - double max_vert = MAX(abs(diag * sin(angle1)), abs(diag * sin(angle2))); - int center_x = (block_x1 + block_x2) / 2 / current_downsample; - int center_y = (block_y1 + block_y2) / 2 / current_downsample; - int x1 = center_x - max_horiz / 2; - int y1 = center_y - max_vert / 2; - int x2 = x1 + max_horiz; - int y2 = y1 + max_vert; - CLAMP(x1, 0, downsampled_current_w - 1); - CLAMP(y1, 0, downsampled_current_h - 1); - CLAMP(x2, 0, downsampled_current_w - 1); - CLAMP(y2, 0, downsampled_current_h - 1); - -//printf("MotionScan::pixel_search %d %f %f %d %d\n", -//__LINE__, TO_DEG(angle1), TO_DEG(angle2), (int)max_horiz, (int)max_vert); - rotater->set_in_viewport(x1, - y1, - x2 - x1, - y2 - y1); - rotater->set_out_viewport(x1, - y1, - x2 - x1, - y2 - y1); - -// rotater->set_in_viewport(0, -// 0, -// downsampled_current_w, -// downsampled_current_h); -// rotater->set_out_viewport(0, -// 0, -// downsampled_current_w, -// downsampled_current_h); - - rotater->set_in_pivot(center_x, center_y); - rotater->set_out_pivot(center_x, center_y); - - rotater->rotate(rotated_current[i], - current_frame, - step_to_angle(i, r_result)); - -// rotated_current[i]->draw_rect(block_x1 / current_downsample, -// block_y1 / current_downsample, -// block_x2 / current_downsample, -// block_y2 / current_downsample); -// char string[BCTEXTLEN]; -// sprintf(string, "/tmp/rotated%d", i); -// rotated_current[i]->write_png(string); -//downsampled_previous->write_png("/tmp/previous"); -//printf("MotionScan::pixel_search %d\n", __LINE__); - } - } - - - - - - -// printf("MotionScan::pixel_search %d block x=%d y=%d w=%d h=%d\n", -// __LINE__, -// block_x1 / current_downsample, -// block_y1 / current_downsample, -// block_w / current_downsample, -// block_h / current_downsample); - - - - - - - -//exit(1); -// Test only translation of the middle rotated frame - rotation_pass = 0; - total_steps = x_steps * y_steps; - set_package_count(total_steps); - process_packages(); - - - - - - -// Get least difference - int64_t min_difference = -1; -#ifdef STDDEV_TEST - double stddev_table[get_total_packages()]; -#endif - for(int i = 0; i < get_total_packages(); i++) - { - MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); - -#ifdef STDDEV_TEST - double stddev = sqrt(pkg->difference1) / - (block_w / current_downsample) / - (block_h / current_downsample) / - 3; -// printf("MotionScan::pixel_search %d current_downsample=%d search_x=%d search_y=%d diff1=%f\n", -// __LINE__, -// current_downsample, -// pkg->search_x, -// pkg->search_y, -// sqrt(pkg->difference1) / block_w / current_downsample / block_h / 3 /* / variance */); - -// printf("MotionScan::pixel_search %d range1=%f stddev=%f\n", -// __LINE__, -// range1, -// stddev); - - stddev_table[i] = stddev; -#endif // STDDEV_TEST - - if(pkg->difference1 < min_difference || i == 0) - { - min_difference = pkg->difference1; - x_result = pkg->search_x * current_downsample * OVERSAMPLE; - y_result = pkg->search_y * current_downsample * OVERSAMPLE; - -// printf("MotionScan::pixel_search %d x_result=%d y_result=%d angle_step=%d diff=%lld\n", -// __LINE__, -// block_x1 * OVERSAMPLE - x_result, -// block_y1 * OVERSAMPLE - y_result, -// pkg->angle_step, -// pkg->difference1); - - } - } - - -#ifdef STDDEV_TEST - qsort(stddev_table, get_total_packages(), sizeof(double), compare); - - -// reject motion vector if not similar enough -// if(stddev_table[0] > 0.2) -// { -// if(debug) -// { -// printf("MotionScan::pixel_search %d stddev fail min_stddev=%f\n", -// __LINE__, -// stddev_table[0]); -// } -// failed = 1; -// return; -// } - -if(debug) -{ - printf("MotionScan::pixel_search %d\n", __LINE__); - for(int i = 0; i < get_total_packages(); i++) - { - printf("%f\n", stddev_table[i]); - } -} - -// reject motion vector if not a sigmoid curve -// TODO: use linear interpolation - int steps = 2; - int step = get_total_packages() / steps; - double curve[steps]; - for(int i = 0; i < steps; i++) - { - int start = get_total_packages() * i / steps; - int end = get_total_packages() * (i + 1) / steps; - end = MIN(end, get_total_packages() - 1); - curve[i] = stddev_table[end] - stddev_table[start]; - } - - -// if(curve[0] < (curve[1] * 1.01) || -// curve[2] < (curve[1] * 1.01) || -// curve[0] < (curve[2] * 0.75)) -// if(curve[0] < curve[1]) -// { -// if(debug) -// { -// printf("MotionScan::pixel_search %d curve fail %f %f\n", -// __LINE__, -// curve[0], -// curve[1]); -// } -// failed = 1; -// return; -// } - -if(debug) -{ -printf("MotionScan::pixel_search %d curve=%f %f ranges=%f %f min_stddev=%f\n", -__LINE__, -curve[0], -curve[1], -range1, -range2, -stddev_table[0]); -} -#endif // STDDEV_TEST - - - - - - if(do_rotate) - { - rotation_pass = 1;; - total_steps = angle_steps; - scan_x1 = x_result / OVERSAMPLE; - scan_y1 = y_result / OVERSAMPLE; - set_package_count(total_steps); - process_packages(); - + pkg->search_x = pkg->scan_x1 + pkg->sub_x / OVERSAMPLE + 1; + pkg->search_y = pkg->scan_y1 + pkg->sub_y / OVERSAMPLE + 1; + pkg->sub_x %= OVERSAMPLE; + pkg->sub_y %= OVERSAMPLE; - min_difference = -1; - double prev_r_result = r_result; - for(int i = 0; i < get_total_packages(); i++) - { - MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); -// printf("MotionScan::pixel_search %d search_x=%d search_y=%d angle_step=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", +// printf("MotionScan::init_packages %d i=%d search_x=%d search_y=%d sub_x=%d sub_y=%d\n", // __LINE__, +// i, // pkg->search_x, // pkg->search_y, -// pkg->search_angle_step, // pkg->sub_x, -// pkg->sub_y, -// pkg->difference1, -// pkg->difference2); - if(pkg->difference1 < min_difference || i == 0) - { - min_difference = pkg->difference1; - r_result = step_to_angle(i, prev_r_result); - - // printf("MotionScan::pixel_search %d x_result=%d y_result=%d angle_step=%d diff=%lld\n", - // __LINE__, - // block_x1 * OVERSAMPLE - x_result, - // block_y1 * OVERSAMPLE - y_result, - // pkg->angle_step, - // pkg->difference1); - } +// pkg->sub_y); } - } - -// printf("MotionScan::scan_frame %d current_downsample=%d x_result=%f y_result=%f r_result=%f\n", +// printf("MotionScan::init_packages %d %d,%d %d,%d %d,%d\n", // __LINE__, -// current_downsample, -// (float)x_result / OVERSAMPLE, -// (float)y_result / OVERSAMPLE, -// r_result); - -} - - -// subpixel motion search -void MotionScan::subpixel_search(int &x_result, int &y_result) -{ - rotation_pass = 0; - previous_frame = previous_frame_arg; - current_frame = current_frame_arg; - -//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result); -// Scan every subpixel in a SUBPIXEL_RANGE * SUBPIXEL_RANGE square - total_steps = (SUBPIXEL_RANGE * OVERSAMPLE) * (SUBPIXEL_RANGE * OVERSAMPLE); - -// These aren't used in subpixel - x_steps = OVERSAMPLE * SUBPIXEL_RANGE; - y_steps = OVERSAMPLE * SUBPIXEL_RANGE; - angle_steps = 1; - - set_package_count(this->total_steps); - process_packages(); - -// Get least difference - int64_t min_difference = -1; - for(int i = 0; i < get_total_packages(); i++) - { - MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); -//printf("MotionScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", -//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2); - if(pkg->difference1 < min_difference || min_difference == -1) - { - min_difference = pkg->difference1; - -// The sub coords are 1 pixel up & left of the block coords - x_result = pkg->search_x * OVERSAMPLE + pkg->sub_x; - y_result = pkg->search_y * OVERSAMPLE + pkg->sub_y; - +// scan_x1, +// scan_x2, +// scan_y1, +// scan_y2, +// pkg->search_x, +// pkg->search_y); + } +} -// Fill in results - dx_result = block_x1 * OVERSAMPLE - x_result; - dy_result = block_y1 * OVERSAMPLE - y_result; -//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", -//__LINE__, dx_result, dy_result, min_difference); - } +LoadClient* MotionScan::new_client() +{ + return new MotionScanUnit(this); +} - if(pkg->difference2 < min_difference) - { - min_difference = pkg->difference2; +LoadPackage* MotionScan::new_package() +{ + return new MotionScanPackage; +} - x_result = pkg->search_x * OVERSAMPLE - pkg->sub_x; - y_result = pkg->search_y * OVERSAMPLE - pkg->sub_y; - dx_result = block_x1 * OVERSAMPLE - x_result; - dy_result = block_y1 * OVERSAMPLE - y_result; -//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", -//__LINE__, dx_result, dy_result, min_difference); - } - } +void MotionScan::set_test_match(int value) +{ + this->test_match = value; } - void MotionScan::scan_frame(VFrame *previous_frame, VFrame *current_frame, int global_range_w, int global_range_h, int global_block_w, int global_block_h, - int block_x, - int block_y, + double block_x, + double block_y, int frame_type, int tracking_type, int action_type, int horizontal_only, int vertical_only, int source_position, + int total_steps, int total_dx, int total_dy, int global_origin_x, - int global_origin_y, - int do_motion, - int do_rotate, - double rotation_center, - double rotation_range) + int global_origin_y) { this->previous_frame_arg = previous_frame; this->current_frame_arg = current_frame; @@ -1085,51 +351,25 @@ void MotionScan::scan_frame(VFrame *previous_frame, this->current_frame = current_frame_arg; this->global_origin_x = global_origin_x; this->global_origin_y = global_origin_y; - this->action_type = action_type; - this->do_motion = do_motion; - this->do_rotate = do_rotate; - this->rotation_center = rotation_center; - this->rotation_range = rotation_range; - -//printf("MotionScan::scan_frame %d\n", __LINE__); - dx_result = 0; - dy_result = 0; - dr_result = 0; - failed = 0; - subpixel = 0; -// starting level of detail -// TODO: base it on a table of resolutions - current_downsample = STARTING_DOWNSAMPLE; - angle_step = 0; + + cache.remove_all_objects(); // Single macroblock int w = current_frame->get_w(); int h = current_frame->get_h(); // Initial search parameters - scan_w = global_range_w; - scan_h = global_range_h; - - int block_w = global_block_w; - int block_h = global_block_h; - -// printf("MotionScan::scan_frame %d %d %d %d %d %d %d %d %d\n", -// __LINE__, -// global_range_w, -// global_range_h, -// global_block_w, -// global_block_h, -// scan_w, -// scan_h, -// block_w, -// block_h); + int scan_w = w * global_range_w / 100; + int scan_h = h * global_range_h / 100; + int block_w = w * global_block_w / 100; + int block_h = h * global_block_h / 100; // Location of block in previous frame - block_x1 = (int)(block_x - block_w / 2); - block_y1 = (int)(block_y - block_h / 2); - block_x2 = (int)(block_x + block_w / 2); - block_y2 = (int)(block_y + block_h / 2); + block_x1 = (int)(w * block_x / 100 - block_w / 2); + block_y1 = (int)(h * block_y / 100 - block_h / 2); + block_x2 = (int)(w * block_x / 100 + block_w / 2); + block_y2 = (int)(h * block_y / 100 + block_h / 2); // Offset to location of previous block. This offset needn't be very accurate // since it's the offset of the previous image and current image we want. @@ -1149,7 +389,6 @@ void MotionScan::scan_frame(VFrame *previous_frame, case MotionScan::NO_CALCULATE: dx_result = 0; dy_result = 0; - dr_result = rotation_center; skip = 1; break; @@ -1157,55 +396,21 @@ void MotionScan::scan_frame(VFrame *previous_frame, { // Load result from disk char string[BCTEXTLEN]; - - skip = 1; - if(do_motion) - { - sprintf(string, "%s%06d", - MOTION_FILE, - source_position); + sprintf(string, "%s%06d", + MOTION_FILE, + source_position); //printf("MotionScan::scan_frame %d %s\n", __LINE__, string); - FILE *input = fopen(string, "r"); - if(input) - { - int temp = fscanf(input, - "%d %d", - &dx_result, - &dy_result); - if( temp != 2 ) - printf("MotionScan::scan_frame %d %s\n", __LINE__, string); + FILE *input = fopen(string, "r"); + if(input) + { + (void)fscanf(input, "%d %d", + &dx_result, &dy_result); // HACK //dx_result *= 2; //dy_result *= 2; //printf("MotionScan::scan_frame %d %d %d\n", __LINE__, dx_result, dy_result); - fclose(input); - } - else - { - skip = 0; - } - } - - if(do_rotate) - { - sprintf(string, - "%s%06d", - ROTATION_FILE, - source_position); - FILE *input = fopen(string, "r"); - if(input) - { - int temp = fscanf(input, "%f", &dr_result); - if( temp != 1 ) - printf("MotionScan::scan_frame %d %s\n", __LINE__, string); -// DEBUG -//dr_result += 0.25; - fclose(input); - } - else - { - skip = 0; - } + fclose(input); + skip = 1; } break; } @@ -1216,8 +421,6 @@ void MotionScan::scan_frame(VFrame *previous_frame, break; } - - if(!skip && test_match) { if(previous_frame->data_matches(current_frame)) @@ -1225,21 +428,19 @@ void MotionScan::scan_frame(VFrame *previous_frame, printf("MotionScan::scan_frame: data matches. skipping.\n"); dx_result = 0; dy_result = 0; - dr_result = rotation_center; skip = 1; } } - // Perform scan if(!skip) { +//printf("MotionScan::scan_frame %d\n", __LINE__); // Location of block in current frame - int origin_offset_x = this->global_origin_x; - int origin_offset_y = this->global_origin_y; + int origin_offset_x = this->global_origin_x * w / 100; + int origin_offset_y = this->global_origin_y * h / 100; int x_result = block_x1 + origin_offset_x; int y_result = block_y1 + origin_offset_y; - double r_result = rotation_center; // printf("MotionScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", // block_x1 + block_w / 2, @@ -1251,31 +452,32 @@ printf("MotionScan::scan_frame: data matches. skipping.\n"); // block_x2, // block_y2); - while(!failed) + while(1) { +// Cache needs to be cleared if downsampling is used because the sums of +// different downsamplings can't be compared. +// Subpixel never uses the cache. +// cache.remove_all_objects(); scan_x1 = x_result - scan_w / 2; scan_y1 = y_result - scan_h / 2; scan_x2 = x_result + scan_w / 2; scan_y2 = y_result + scan_h / 2; - scan_angle1 = r_result - rotation_range; - scan_angle2 = r_result + rotation_range; // Zero out requested values -// if(horizontal_only) -// { -// scan_y1 = block_y1; -// scan_y2 = block_y1 + 1; -// } -// if(vertical_only) -// { -// scan_x1 = block_x1; -// scan_x2 = block_x1 + 1; -// } - -// printf("MotionScan::scan_frame %d block_x1=%d block_y1=%d block_x2=%d block_y2=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d\n", -// __LINE__, + if(horizontal_only) + { + scan_y1 = block_y1; + scan_y2 = block_y1 + 1; + } + if(vertical_only) + { + scan_x1 = block_x1; + scan_x2 = block_x1 + 1; + } + +// printf("MotionScan::scan_frame 1 %d %d %d %d %d %d %d %d\n", // block_x1, // block_y1, // block_x2, @@ -1284,11 +486,9 @@ printf("MotionScan::scan_frame: data matches. skipping.\n"); // scan_y1, // scan_x2, // scan_y2); - - // Clamp the block coords before the scan so we get useful scan coords. - clamp_scan(w, - h, + clamp_scan(w, + h, &block_x1, &block_y1, &block_x2, @@ -1298,21 +498,18 @@ printf("MotionScan::scan_frame: data matches. skipping.\n"); &scan_x2, &scan_y2, 0); - - -// printf("MotionScan::scan_frame %d block_x1=%d block_y1=%d block_x2=%d block_y2=%d scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d x_result=%d y_result=%d\n", +// printf("MotionScan::scan_frame 1 %d block_x1=%d block_y1=%d block_x2=%d block_y2=%d\n scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d\n x_result=%d y_result=%d\n", // __LINE__, // block_x1, // block_y1, // block_x2, // block_y2, -// scan_x1, -// scan_y1, -// scan_x2, -// scan_y2, -// x_result, +// scan_x1, +// scan_y1, +// scan_x2, +// scan_y2, +// x_result, // y_result); -//if(y_result == 88) exit(0); // Give up if invalid coords. @@ -1320,49 +517,179 @@ printf("MotionScan::scan_frame: data matches. skipping.\n"); scan_x2 <= scan_x1 || block_x2 <= block_x1 || block_y2 <= block_y1) - { break; - } // For subpixel, the top row and left column are skipped if(subpixel) { - subpixel_search(x_result, y_result); -// printf("MotionScan::scan_frame %d x_result=%d y_result=%d\n", -// __LINE__, -// x_result / OVERSAMPLE, -// y_result / OVERSAMPLE); +//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result); +// Scan every subpixel in a 2 pixel * 2 pixel square + total_pixels = (2 * OVERSAMPLE) * (2 * OVERSAMPLE); + + this->total_steps = total_pixels; +// These aren't used in subpixel + this->x_steps = OVERSAMPLE * 2; + this->y_steps = OVERSAMPLE * 2; + + set_package_count(this->total_steps); + process_packages(); + +// Get least difference + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); +//printf("MotionScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", +//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2); + if(pkg->difference1 < min_difference || min_difference == -1) + { + min_difference = pkg->difference1; + +// The sub coords are 1 pixel up & left of the block coords + x_result = pkg->search_x * OVERSAMPLE + pkg->sub_x; + y_result = pkg->search_y * OVERSAMPLE + pkg->sub_y; + + +// Fill in results + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; +//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", +//__LINE__, dx_result, dy_result, min_difference); + } + + if(pkg->difference2 < min_difference) + { + min_difference = pkg->difference2; + + x_result = pkg->search_x * OVERSAMPLE - pkg->sub_x; + y_result = pkg->search_y * OVERSAMPLE - pkg->sub_y; + + dx_result = block_x1 * OVERSAMPLE - x_result; + dy_result = block_y1 * OVERSAMPLE - y_result; +//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", +//__LINE__, dx_result, dy_result, min_difference); + } + } break; } else // Single pixel { - pixel_search(x_result, y_result, r_result); -//printf("MotionScan::scan_frame %d x_result=%d y_result=%d\n", __LINE__, x_result / OVERSAMPLE, y_result / OVERSAMPLE); + total_pixels = (scan_x2 - scan_x1) * (scan_y2 - scan_y1); + this->total_steps = MIN(total_steps, total_pixels); - if(failed) + if(this->total_steps == total_pixels) { - dr_result = 0; - dx_result = 0; - dy_result = 0; + x_steps = scan_x2 - scan_x1; + y_steps = scan_y2 - scan_y1; } else - if(current_downsample <= 1) { - // Single pixel accuracy reached. Now do exhaustive subpixel search. + x_steps = (int)sqrt(this->total_steps); + y_steps = (int)sqrt(this->total_steps); + } + +// Use downsampled images +// if(scan_x2 - scan_x1 > x_steps * 4 || +// scan_y2 - scan_y1 > y_steps * 4) +// { +// printf("MotionScan::scan_frame %d total_pixels=%d total_steps=%d x_steps=%d y_steps=%d x y steps=%d\n", +// __LINE__, +// total_pixels, +// total_steps, +// x_steps, +// y_steps, +// x_steps * y_steps); +// +// if(!downsampled_previous || +// !downsampled_previous->equivalent(previous_frame_arg)) +// { +// delete downsampled_previous; +// downsampled_previous = new VFrame(*previous_frame_arg); +// } +// +// if(!downsampled_current || +// !downsampled_current->equivalent(current_frame_arg)) +// { +// delete downsampled_current; +// downsampled_current = new VFrame(*current_frame_arg); +// } +// +// +// if(!downsample) +// downsample = new DownSampleServer(get_total_clients(), +// get_total_clients()); +// downsample->process_frame(downsampled_previous, +// previous_frame_arg, +// 1, +// 1, +// 1, +// 1, +// (scan_y2 - scan_y1) / y_steps, +// (scan_x2 - scan_x1) / x_steps, +// 0, +// 0); +// downsample->process_frame(downsampled_current, +// current_frame_arg, +// 1, +// 1, +// 1, +// 1, +// (scan_y2 - scan_y1) / y_steps, +// (scan_x2 - scan_x1) / x_steps, +// 0, +// 0); +// this->previous_frame = downsampled_previous; +// this->current_frame = downsampled_current; +// } + + + + + +// printf("MotionScan::scan_frame %d this->total_steps=%d\n", +// __LINE__, +// this->total_steps); + + + set_package_count(this->total_steps); + process_packages(); + +// Get least difference + int64_t min_difference = -1; + for(int i = 0; i < get_total_packages(); i++) + { + MotionScanPackage *pkg = (MotionScanPackage*)get_package(i); +//printf("MotionScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", +//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2); + if(pkg->difference1 < min_difference || min_difference == -1) + { + min_difference = pkg->difference1; + x_result = pkg->search_x; + y_result = pkg->search_y; + x_result *= OVERSAMPLE; + y_result *= OVERSAMPLE; +//printf("MotionScan::scan_frame %d x_result=%d y_result=%d diff=%lld\n", +//__LINE__, block_x1 * OVERSAMPLE - x_result, block_y1 * OVERSAMPLE - y_result, pkg->difference1); + } + } + + +// If a new search is required, rescale results back to pixels. + if(this->total_steps >= total_pixels) + { +// Single pixel accuracy reached. Now do exhaustive subpixel search. if(action_type == MotionScan::STABILIZE || action_type == MotionScan::TRACK || action_type == MotionScan::NOTHING) { +//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result); x_result /= OVERSAMPLE; y_result /= OVERSAMPLE; -//printf("MotionScan::scan_frame %d x_result=%d y_result=%d\n", __LINE__, x_result, y_result); - scan_w = SUBPIXEL_RANGE; - scan_h = SUBPIXEL_RANGE; -// Final R result - dr_result = rotation_center - r_result; + scan_w = 2; + scan_h = 2; subpixel = 1; } else @@ -1370,109 +697,59 @@ printf("MotionScan::scan_frame: data matches. skipping.\n"); // Fill in results and quit dx_result = block_x1 * OVERSAMPLE - x_result; dy_result = block_y1 * OVERSAMPLE - y_result; - dr_result = rotation_center - r_result; +//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, dx_result, dy_result); break; } } else // Reduce scan area and try again { -// scan_w = (scan_x2 - scan_x1) / 2; -// scan_h = (scan_y2 - scan_y1) / 2; -// need slightly more than 2x downsampling factor - - if(current_downsample * 3 < scan_w && - current_downsample * 3 < scan_h) - { - scan_w = current_downsample * 3; - scan_h = current_downsample * 3; - } - - if(angle_step * 1.5 < rotation_range) - { - rotation_range = angle_step * 1.5; - } -//printf("MotionScan::scan_frame %d %f %f\n", __LINE__, angle_step, rotation_range); - - current_downsample /= 2; - -// convert back to pixels + scan_w = (scan_x2 - scan_x1) / 2; + scan_h = (scan_y2 - scan_y1) / 2; x_result /= OVERSAMPLE; y_result /= OVERSAMPLE; -// debug -//exit(1); } - } } dx_result *= -1; dy_result *= -1; - dr_result *= -1; } -// printf("MotionScan::scan_frame %d dx=%f dy=%f dr=%f\n", -// __LINE__, -// (float)dx_result / OVERSAMPLE, -// (float)dy_result / OVERSAMPLE, -// dr_result); +//printf("MotionScan::scan_frame %d\n", __LINE__); + if(vertical_only) dx_result = 0; + if(horizontal_only) dy_result = 0; + // Write results - if(!skip && tracking_type == MotionScan::SAVE) + if(tracking_type == MotionScan::SAVE) { char string[BCTEXTLEN]; - - - if(do_motion) + sprintf(string, + "%s%06d", + MOTION_FILE, + source_position); + FILE *output = fopen(string, "w"); + if(output) { - sprintf(string, - "%s%06d", - MOTION_FILE, - source_position); - FILE *output = fopen(string, "w"); - if(output) - { - fprintf(output, - "%d %d\n", - dx_result, - dy_result); - fclose(output); - } - else - { - printf("MotionScan::scan_frame %d: save motion failed\n", __LINE__); - } + fprintf(output, + "%d %d\n", + dx_result, + dy_result); + fclose(output); } - - if(do_rotate) + else { - sprintf(string, - "%s%06d", - ROTATION_FILE, - source_position); - FILE *output = fopen(string, "w"); - if(output) - { - fprintf(output, "%f\n", dr_result); - fclose(output); - } - else - { - printf("MotionScan::scan_frame %d save rotation failed\n", __LINE__); - } + printf("MotionScan::scan_frame %d: save coordinate failed", __LINE__); } } - - if(vertical_only) dx_result = 0; - if(horizontal_only) dy_result = 0; - -// printf("MotionScan::scan_frame %d dx=%d dy=%d\n", +// printf("MotionScan::scan_frame %d dx=%.2f dy=%.2f\n", // __LINE__, -// this->dx_result, -// this->dy_result); +// (float)this->dx_result / OVERSAMPLE, +// (float)this->dy_result / OVERSAMPLE); } @@ -1491,6 +768,31 @@ printf("MotionScan::scan_frame: data matches. skipping.\n"); +int64_t MotionScan::get_cache(int x, int y) +{ + int64_t result = -1; + cache_lock->lock("MotionScan::get_cache"); + for(int i = 0; i < cache.total; i++) + { + MotionScanCache *ptr = cache.values[i]; + if(ptr->x == x && ptr->y == y) + { + result = ptr->difference; + break; + } + } + cache_lock->unlock(); + return result; +} + +void MotionScan::put_cache(int x, int y, int64_t difference) +{ + MotionScanCache *ptr = new MotionScanCache(x, y, difference); + cache_lock->lock("MotionScan::put_cache"); + cache.append(ptr); + cache_lock->unlock(); +} + #define ABS_DIFF(type, temp_type, multiplier, components) \ @@ -1506,8 +808,10 @@ printf("MotionScan::scan_frame: data matches. skipping.\n"); { \ temp_type difference; \ difference = *prev_row++ - *current_row++; \ - difference *= difference; \ - result_temp += difference; \ + if(difference < 0) \ + result_temp -= difference; \ + else \ + result_temp += difference; \ } \ if(components == 4) \ { \ @@ -1549,6 +853,12 @@ int64_t MotionScan::abs_diff(unsigned char *prev_ptr, case BC_YUVA8888: ABS_DIFF(unsigned char, int64_t, 1, 4) break; + case BC_YUV161616: + ABS_DIFF(uint16_t, int64_t, 1, 3) + break; + case BC_YUVA16161616: + ABS_DIFF(uint16_t, int64_t, 1, 4) + break; } return result; } @@ -1583,8 +893,10 @@ int64_t MotionScan::abs_diff(unsigned char *prev_ptr, 0x100 / 0x100; \ temp_type current_value = *current_row++; \ difference = prev_value - current_value; \ - difference *= difference; \ - result_temp += difference; \ + if(difference < 0) \ + result_temp -= difference; \ + else \ + result_temp += difference; \ } \ \ /* skip alpha */ \ @@ -1639,161 +951,31 @@ int64_t MotionScan::abs_diff_sub(unsigned char *prev_ptr, case BC_YUVA8888: ABS_DIFF_SUB(unsigned char, int64_t, 1, 4) break; - } - return result; -} - - -#if 0 -#define VARIANCE(type, temp_type, multiplier, components) \ -{ \ - temp_type average[3] = { 0 }; \ - temp_type variance[3] = { 0 }; \ - \ - for(int i = 0; i < h; i++) \ - { \ - type *row = (type*)current_ptr + i * row_bytes; \ - for(int j = 0; j < w; j++) \ - { \ - for(int k = 0; k < 3; k++) \ - { \ - average[k] += row[k]; \ - } \ - row += components; \ - } \ - } \ - for(int k = 0; k < 3; k++) \ - { \ - average[k] /= w * h; \ - } \ - \ - for(int i = 0; i < h; i++) \ - { \ - type *row = (type*)current_ptr + i * row_bytes; \ - for(int j = 0; j < w; j++) \ - { \ - for(int k = 0; k < 3; k++) \ - { \ - variance[k] += SQR(row[k] - average[k]); \ - } \ - row += components; \ - } \ - } \ - result = (double)multiplier * \ - sqrt((variance[0] + variance[1] + variance[2]) / w / h / 3); \ -} - -double MotionScan::calculate_variance(unsigned char *current_ptr, - int row_bytes, - int w, - int h, - int color_model) -{ - double result = 0; - - switch(color_model) - { - case BC_RGB888: - VARIANCE(unsigned char, int, 1, 3) - break; - case BC_RGBA8888: - VARIANCE(unsigned char, int, 1, 4) - break; - case BC_RGB_FLOAT: - VARIANCE(float, double, 255, 3) - break; - case BC_RGBA_FLOAT: - VARIANCE(float, double, 255, 4) - break; - case BC_YUV888: - VARIANCE(unsigned char, int, 1, 3) + case BC_YUV161616: + ABS_DIFF_SUB(uint16_t, int64_t, 1, 3) break; - case BC_YUVA8888: - VARIANCE(unsigned char, int, 1, 4) + case BC_YUVA16161616: + ABS_DIFF_SUB(uint16_t, int64_t, 1, 4) break; } - - return result; } -#endif // 0 -#define RANGE(type, temp_type, multiplier, components) \ -{ \ - temp_type min[3]; \ - temp_type max[3]; \ - min[0] = 0x7fff; \ - min[1] = 0x7fff; \ - min[2] = 0x7fff; \ - max[0] = 0; \ - max[1] = 0; \ - max[2] = 0; \ - \ - for(int i = 0; i < h; i++) \ - { \ - type *row = (type*)current_ptr + i * row_bytes; \ - for(int j = 0; j < w; j++) \ - { \ - for(int k = 0; k < 3; k++) \ - { \ - if(row[k] > max[k]) max[k] = row[k]; \ - if(row[k] < min[k]) min[k] = row[k]; \ - } \ - row += components; \ - } \ - } \ - \ - for(int k = 0; k < 3; k++) \ - { \ - /* printf("MotionScan::calculate_range %d k=%d max=%d min=%d\n", __LINE__, k, max[k], min[k]); */ \ - if(max[k] - min[k] > result) result = max[k] - min[k]; \ - } \ - \ -} -double MotionScan::calculate_range(unsigned char *current_ptr, - int row_bytes, - int w, - int h, - int color_model) +MotionScanCache::MotionScanCache(int x, int y, int64_t difference) { - double result = 0; - - switch(color_model) - { - case BC_RGB888: - RANGE(unsigned char, int, 1, 3) - break; - case BC_RGBA8888: - RANGE(unsigned char, int, 1, 4) - break; - case BC_RGB_FLOAT: - RANGE(float, float, 255, 3) - break; - case BC_RGBA_FLOAT: - RANGE(float, float, 255, 4) - break; - case BC_YUV888: - RANGE(unsigned char, int, 1, 3) - break; - case BC_YUVA8888: - RANGE(unsigned char, int, 1, 4) - break; - } - - - return result; + this->x = x; + this->y = y; + this->difference = difference; } -//#define CLAMP_BLOCK -// this truncates the scan area but not the macroblock unless the macro is defined -void MotionScan::clamp_scan(int w, - int h, +void MotionScan::clamp_scan(int w, + int h, int *block_x1, int *block_y1, int *block_x2, @@ -1824,37 +1006,29 @@ void MotionScan::clamp_scan(int w, // scan is always out of range before block. if(*scan_x1 < 0) { -#ifdef CLAMP_BLOCK - int difference = -*scan_x1; - *block_x1 += difference; -#endif +// int difference = -*scan_x1; +// *block_x1 += difference; *scan_x1 = 0; } if(*scan_y1 < 0) { -#ifdef CLAMP_BLOCK - int difference = -*scan_y1; - *block_y1 += difference; -#endif +// int difference = -*scan_y1; +// *block_y1 += difference; *scan_y1 = 0; } if(*scan_x2 > w) { int difference = *scan_x2 - w; -#ifdef CLAMP_BLOCK - *block_x2 -= difference; -#endif +// *block_x2 -= difference; *scan_x2 -= difference; } if(*scan_y2 > h) { int difference = *scan_y2 - h; -#ifdef CLAMP_BLOCK - *block_y2 -= difference; -#endif +// *block_y2 -= difference; *scan_y2 -= difference; } @@ -1870,9 +1044,7 @@ void MotionScan::clamp_scan(int w, if(*scan_x1 < 0) { int difference = -*scan_x1; -#ifdef CLAMP_BLOCK - *block_x1 += difference; -#endif +// *block_x1 += difference; *scan_x2 += difference; *scan_x1 = 0; } @@ -1880,9 +1052,7 @@ void MotionScan::clamp_scan(int w, if(*scan_y1 < 0) { int difference = -*scan_y1; -#ifdef CLAMP_BLOCK - *block_y1 += difference; -#endif +// *block_y1 += difference; *scan_y2 += difference; *scan_y1 = 0; } @@ -1891,18 +1061,14 @@ void MotionScan::clamp_scan(int w, { int difference = *scan_x2 - *block_x1 + *block_x2 - w; *scan_x2 -= difference; -#ifdef CLAMP_BLOCK - *block_x2 -= difference; -#endif +// *block_x2 -= difference; } if(*scan_y2 - *block_y1 + *block_y2 > h) { int difference = *scan_y2 - *block_y1 + *block_y2 - h; *scan_y2 -= difference; -#ifdef CLAMP_BLOCK - *block_y2 -= difference; -#endif +// *block_y2 -= difference; } // CLAMP(*scan_x1, 0, w - (*block_x2 - *block_x1)); diff --git a/cinelerra-5.1/plugins/motion/motionscan.h b/cinelerra-5.1/plugins/motion/motionscan.h index 72c52980..8e756ee3 100644 --- a/cinelerra-5.1/plugins/motion/motionscan.h +++ b/cinelerra-5.1/plugins/motion/motionscan.h @@ -1,29 +1,30 @@ /* * CINELERRA - * Copyright (C) 2016 Adam Williams - * + * Copyright (C) 2008 Adam Williams + * * 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 - * + * */ #ifndef MOTIONSCAN_H #define MOTIONSCAN_H -#include "affine.inc" +#include "arraylist.h" +//#include "../downsample/downsampleengine.inc" #include "loadbalance.h" #include "vframe.inc" #include @@ -32,7 +33,6 @@ class MotionScan; #define OVERSAMPLE 4 #define MOTION_FILE "/tmp/m" -#define ROTATION_FILE "/tmp/r" class MotionScanPackage : public LoadPackage { @@ -40,11 +40,10 @@ public: MotionScanPackage(); // For multiple blocks -// Position of stationary block after downsampling +// Position of stationary block int block_x1, block_y1, block_x2, block_y2; -// index of rotated frame - int angle_step; - +// Range of positions to scan + int scan_x1, scan_y1, scan_x2, scan_y2; int dx; int dy; int64_t max_difference; @@ -52,9 +51,11 @@ public: int64_t min_pixel; int is_border; int valid; +// For single block + int step; int64_t difference1; int64_t difference2; -// Search position of current package to nearest pixel with downsampling +// Search position to nearest pixel int search_x; int search_y; // Subpixel of search position @@ -62,6 +63,14 @@ public: int sub_y; }; +class MotionScanCache +{ +public: + MotionScanCache(int x, int y, int64_t difference); + int x, y; + int64_t difference; +}; + class MotionScanUnit : public LoadClient { public: @@ -69,16 +78,19 @@ public: ~MotionScanUnit(); void process_package(LoadPackage *package); - void subpixel(MotionScanPackage *pkg); - void single_pixel(MotionScanPackage *pkg); + int64_t get_cache(int x, int y); + void put_cache(int x, int y, int64_t difference); MotionScan *server; + + ArrayList cache; + Mutex *cache_lock; }; class MotionScan : public LoadServer { public: - MotionScan(int total_clients, + MotionScan(int total_clients, int total_packages); ~MotionScan(); @@ -93,27 +105,27 @@ public: // Invoke the motion engine for a search // Frame before motion void scan_frame(VFrame *previous_frame, +// Frame after motion VFrame *current_frame, - int global_range_w, // in pixels + int global_range_w, int global_range_h, - int global_block_w, // in pixels + int global_block_w, int global_block_h, - int block_x, // in pixels - int block_y, + double block_x, + double block_y, int frame_type, int tracking_type, int action_type, int horizontal_only, int vertical_only, int source_position, - int total_dx, // in pixels * OVERSAMPLE + int total_steps, + int total_dx, int total_dy, - int global_origin_x, // in pixels - int global_origin_y, - int do_motion, - int do_rotate, - double rotation_center, // in deg - double rotation_range); + int global_origin_x, + int global_origin_y); + int64_t get_cache(int x, int y); + void put_cache(int x, int y, int64_t difference); static int64_t abs_diff(unsigned char *prev_ptr, unsigned char *current_ptr, @@ -131,8 +143,8 @@ public: int sub_y); - static void clamp_scan(int w, - int h, + static void clamp_scan(int w, + int h, int *block_x1, int *block_y1, int *block_x2, @@ -143,11 +155,10 @@ public: int *scan_y2, int use_absolute); -// Change between previous frame and current frame multiplied by +// Change between previous frame and current frame multiplied by // OVERSAMPLE int dx_result; int dy_result; - float dr_result; enum { @@ -158,7 +169,7 @@ public: STABILIZE_PIXEL, NOTHING }; - + enum { // tracking_type @@ -167,7 +178,7 @@ public: LOAD, NO_CALCULATE }; - + enum { // frame_type @@ -177,27 +188,6 @@ public: }; private: - void downsample_frame(VFrame *dst, - VFrame *src, - int downsample); - void pixel_search(int &x_result, int &y_result, double &r_result); - void subpixel_search(int &x_result, int &y_result); - double step_to_angle(int step, double center); - -// double calculate_variance(unsigned char *current_ptr, -// int row_bytes, -// int w, -// int h, -// int color_model); - double calculate_range(unsigned char *current_ptr, - int row_bytes, - int w, - int h, - int color_model); - - - - AffineEngine *rotater; // Pointer to downsampled frame before motion VFrame *previous_frame; // Pointer to downsampled frame after motion @@ -208,49 +198,33 @@ private: // Downsampled frames VFrame *downsampled_previous; VFrame *downsampled_current; -// rotated versions of current_frame - VFrame **rotated_current; -// allocation of rotated_current array, a copy of angle_steps - int total_rotated; // Test for identical frames before processing // Faster to skip it if the frames are usually different int test_match; int skip; -// macroblocks didn't have enough data - int failed; // For single block int block_x1; int block_x2; int block_y1; int block_y2; - int scan_w; - int scan_h; int scan_x1; int scan_y1; int scan_x2; int scan_y2; - double scan_angle1, scan_angle2; + int total_pixels; + int total_steps; + int edge_steps; int y_steps; int x_steps; - int angle_steps; -// in deg - double angle_step; int subpixel; int horizontal_only; int vertical_only; int global_origin_x; int global_origin_y; - int action_type; - int current_downsample; - int downsampled_w; - int downsampled_h; - int total_steps; - int do_motion; - int do_rotate; - int rotation_pass; -// in deg - double rotation_center; - double rotation_range; + + ArrayList cache; + Mutex *cache_lock; +// DownSampleServer *downsample; }; diff --git a/cinelerra-5.1/plugins/motion/motionscan.inc b/cinelerra-5.1/plugins/motion/motionscan.inc index 4e8229ed..3c574345 100644 --- a/cinelerra-5.1/plugins/motion/motionscan.inc +++ b/cinelerra-5.1/plugins/motion/motionscan.inc @@ -2,21 +2,21 @@ /* * CINELERRA * Copyright (C) 2008 Adam Williams - * + * * 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 - * + * */ #ifndef MOTIONSCAN_INC diff --git a/cinelerra-5.1/plugins/motion/motionwindow.C b/cinelerra-5.1/plugins/motion/motionwindow.C index 08c4022c..02972d15 100644 --- a/cinelerra-5.1/plugins/motion/motionwindow.C +++ b/cinelerra-5.1/plugins/motion/motionwindow.C @@ -53,10 +53,10 @@ void MotionWindow::create_objects() -// add_subwindow(global = new MotionGlobal(plugin, -// this, -// x1, -// y)); + add_subwindow(global = new MotionGlobal(plugin, + this, + x1, + y)); add_subwindow(rotate = new MotionRotate(plugin, this, @@ -108,20 +108,20 @@ void MotionWindow::create_objects() // y, // &plugin->config.rotation_block_h)); -// y += 50; -// add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:"))); -// add_subwindow(global_search_positions = new GlobalSearchPositions(plugin, -// x1 + title->get_w() + 10, -// y, -// 80)); -// global_search_positions->create_objects(); -// -// add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:"))); -// add_subwindow(rotation_search_positions = new RotationSearchPositions(plugin, -// x2 + title->get_w() + 10, -// y, -// 80)); -// rotation_search_positions->create_objects(); + y += 50; + add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:"))); + add_subwindow(global_search_positions = new GlobalSearchPositions(plugin, + x1 + title->get_w() + 10, + y, + 80)); + global_search_positions->create_objects(); + + add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:"))); + add_subwindow(rotation_search_positions = new RotationSearchPositions(plugin, + x2 + title->get_w() + 10, + y, + 80)); + rotation_search_positions->create_objects(); y += 50; add_subwindow(title = new BC_Title(x, y, _("Translation direction:"))); @@ -209,6 +209,11 @@ void MotionWindow::create_objects() this, x + track_single->get_w() + title->get_w() + 20, y)); + add_subwindow(addtrackedframeoffset = new AddTrackedFrameOffset(plugin, + this, + x + track_single->get_w() + title->get_w() + 20 + track_frame_number->get_w(), + y)); + y += 20; add_subwindow(track_previous = new TrackPreviousFrame(plugin, @@ -268,8 +273,9 @@ void MotionWindow::update_mode() MIN_ROTATION, MAX_ROTATION); vectors->update(plugin->config.draw_vectors); -// global->update(plugin->config.global); + global->update(plugin->config.global); rotate->update(plugin->config.rotate); + addtrackedframeoffset->update(plugin->config.addtrackedframeoffset); } @@ -391,81 +397,81 @@ int BlockSize::handle_event() -// GlobalSearchPositions::GlobalSearchPositions(MotionMain *plugin, -// int x, -// int y, -// int w) -// : BC_PopupMenu(x, -// y, -// w, -// "", -// 1) -// { -// this->plugin = plugin; -// } -// void GlobalSearchPositions::create_objects() -// { -// add_item(new BC_MenuItem("16")); -// add_item(new BC_MenuItem("32")); -// add_item(new BC_MenuItem("64")); -// add_item(new BC_MenuItem("128")); -// add_item(new BC_MenuItem("256")); -// add_item(new BC_MenuItem("512")); -// add_item(new BC_MenuItem("1024")); -// add_item(new BC_MenuItem("2048")); -// add_item(new BC_MenuItem("4096")); -// add_item(new BC_MenuItem("8192")); -// add_item(new BC_MenuItem("16384")); -// add_item(new BC_MenuItem("32768")); -// add_item(new BC_MenuItem("65536")); -// add_item(new BC_MenuItem("131072")); -// char string[BCTEXTLEN]; -// sprintf(string, "%d", plugin->config.global_positions); -// set_text(string); -// } -// -// int GlobalSearchPositions::handle_event() -// { -// plugin->config.global_positions = atoi(get_text()); -// plugin->send_configure_change(); -// return 1; -// } -// -// -// -// -// -// -// -// RotationSearchPositions::RotationSearchPositions(MotionMain *plugin, -// int x, -// int y, -// int w) -// : BC_PopupMenu(x, -// y, -// w, -// "", -// 1) -// { -// this->plugin = plugin; -// } -// void RotationSearchPositions::create_objects() -// { -// add_item(new BC_MenuItem("4")); -// add_item(new BC_MenuItem("8")); -// add_item(new BC_MenuItem("16")); -// add_item(new BC_MenuItem("32")); -// char string[BCTEXTLEN]; -// sprintf(string, "%d", plugin->config.rotate_positions); -// set_text(string); -// } -// -// int RotationSearchPositions::handle_event() -// { -// plugin->config.rotate_positions = atoi(get_text()); -// plugin->send_configure_change(); -// return 1; -// } +GlobalSearchPositions::GlobalSearchPositions(MotionMain *plugin, + int x, + int y, + int w) + : BC_PopupMenu(x, + y, + w, + "", + 1) +{ + this->plugin = plugin; +} +void GlobalSearchPositions::create_objects() +{ + add_item(new BC_MenuItem("16")); + add_item(new BC_MenuItem("32")); + add_item(new BC_MenuItem("64")); + add_item(new BC_MenuItem("128")); + add_item(new BC_MenuItem("256")); + add_item(new BC_MenuItem("512")); + add_item(new BC_MenuItem("1024")); + add_item(new BC_MenuItem("2048")); + add_item(new BC_MenuItem("4096")); + add_item(new BC_MenuItem("8192")); + add_item(new BC_MenuItem("16384")); + add_item(new BC_MenuItem("32768")); + add_item(new BC_MenuItem("65536")); + add_item(new BC_MenuItem("131072")); + char string[BCTEXTLEN]; + sprintf(string, "%d", plugin->config.global_positions); + set_text(string); +} + +int GlobalSearchPositions::handle_event() +{ + plugin->config.global_positions = atoi(get_text()); + plugin->send_configure_change(); + return 1; +} + + + + + + + +RotationSearchPositions::RotationSearchPositions(MotionMain *plugin, + int x, + int y, + int w) + : BC_PopupMenu(x, + y, + w, + "", + 1) +{ + this->plugin = plugin; +} +void RotationSearchPositions::create_objects() +{ + add_item(new BC_MenuItem("4")); + add_item(new BC_MenuItem("8")); + add_item(new BC_MenuItem("16")); + add_item(new BC_MenuItem("32")); + char string[BCTEXTLEN]; + sprintf(string, "%d", plugin->config.rotate_positions); + set_text(string); +} + +int RotationSearchPositions::handle_event() +{ + plugin->config.rotate_positions = atoi(get_text()); + plugin->send_configure_change(); + return 1; +} @@ -515,6 +521,27 @@ int MotionReturnSpeed::handle_event() +AddTrackedFrameOffset::AddTrackedFrameOffset(MotionMain *plugin, + MotionWindow *gui, + int x, + int y) + : BC_CheckBox(x, + y, + plugin->config.addtrackedframeoffset, + _("Add (loaded) offset from tracked frame")) +{ + this->plugin = plugin; + this->gui = gui; +} + +int AddTrackedFrameOffset::handle_event() +{ + plugin->config.addtrackedframeoffset = get_value(); + plugin->send_configure_change(); + return 1; +} + + MotionRMagnitude::MotionRMagnitude(MotionMain *plugin, int x, int y) @@ -559,25 +586,25 @@ int MotionRReturnSpeed::handle_event() -// MotionGlobal::MotionGlobal(MotionMain *plugin, -// MotionWindow *gui, -// int x, -// int y) -// : BC_CheckBox(x, -// y, -// plugin->config.global, -// _("Track translation")) -// { -// this->plugin = plugin; -// this->gui = gui; -// } -// -// int MotionGlobal::handle_event() -// { -// plugin->config.global = get_value(); -// plugin->send_configure_change(); -// return 1; -// } +MotionGlobal::MotionGlobal(MotionMain *plugin, + MotionWindow *gui, + int x, + int y) + : BC_CheckBox(x, + y, + plugin->config.global, + _("Track translation")) +{ + this->plugin = plugin; + this->gui = gui; +} + +int MotionGlobal::handle_event() +{ + plugin->config.global = get_value(); + plugin->send_configure_change(); + return 1; +} MotionRotate::MotionRotate(MotionMain *plugin, MotionWindow *gui, diff --git a/cinelerra-5.1/plugins/motion/motionwindow.h b/cinelerra-5.1/plugins/motion/motionwindow.h index ef977ccb..4a66a1a6 100644 --- a/cinelerra-5.1/plugins/motion/motionwindow.h +++ b/cinelerra-5.1/plugins/motion/motionwindow.h @@ -2,21 +2,21 @@ /* * CINELERRA * Copyright (C) 2008 Adam Williams - * + * * 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 "guicast.h" @@ -78,9 +78,9 @@ public: class TrackSingleFrame : public BC_Radial { public: - TrackSingleFrame(MotionMain *plugin, + TrackSingleFrame(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionMain *plugin; @@ -90,9 +90,9 @@ public: class TrackFrameNumber : public BC_TextBox { public: - TrackFrameNumber(MotionMain *plugin, + TrackFrameNumber(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionMain *plugin; @@ -102,9 +102,9 @@ public: class TrackPreviousFrame : public BC_Radial { public: - TrackPreviousFrame(MotionMain *plugin, + TrackPreviousFrame(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionMain *plugin; @@ -114,9 +114,9 @@ public: class PreviousFrameSameBlock : public BC_Radial { public: - PreviousFrameSameBlock(MotionMain *plugin, + PreviousFrameSameBlock(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionMain *plugin; @@ -126,8 +126,8 @@ public: class GlobalRange : public BC_IPot { public: - GlobalRange(MotionMain *plugin, - int x, + GlobalRange(MotionMain *plugin, + int x, int y, int *value); int handle_event(); @@ -138,8 +138,8 @@ public: class RotationRange : public BC_IPot { public: - RotationRange(MotionMain *plugin, - int x, + RotationRange(MotionMain *plugin, + int x, int y); int handle_event(); MotionMain *plugin; @@ -148,8 +148,8 @@ public: class RotationCenter : public BC_IPot { public: - RotationCenter(MotionMain *plugin, - int x, + RotationCenter(MotionMain *plugin, + int x, int y); int handle_event(); MotionMain *plugin; @@ -158,8 +158,8 @@ public: class BlockSize : public BC_IPot { public: - BlockSize(MotionMain *plugin, - int x, + BlockSize(MotionMain *plugin, + int x, int y, int *value); int handle_event(); @@ -170,9 +170,9 @@ public: class MotionBlockX : public BC_FPot { public: - MotionBlockX(MotionMain *plugin, + MotionBlockX(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionWindow *gui; @@ -182,9 +182,9 @@ public: class MotionBlockY : public BC_FPot { public: - MotionBlockY(MotionMain *plugin, + MotionBlockY(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionWindow *gui; @@ -194,9 +194,9 @@ public: class MotionBlockXText : public BC_TextBox { public: - MotionBlockXText(MotionMain *plugin, + MotionBlockXText(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionWindow *gui; @@ -206,44 +206,44 @@ public: class MotionBlockYText : public BC_TextBox { public: - MotionBlockYText(MotionMain *plugin, + MotionBlockYText(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionWindow *gui; MotionMain *plugin; }; -// class GlobalSearchPositions : public BC_PopupMenu -// { -// public: -// GlobalSearchPositions(MotionMain *plugin, -// int x, -// int y, -// int w); -// void create_objects(); -// int handle_event(); -// MotionMain *plugin; -// }; -// -// class RotationSearchPositions : public BC_PopupMenu -// { -// public: -// RotationSearchPositions(MotionMain *plugin, -// int x, -// int y, -// int w); -// void create_objects(); -// int handle_event(); -// MotionMain *plugin; -// }; +class GlobalSearchPositions : public BC_PopupMenu +{ +public: + GlobalSearchPositions(MotionMain *plugin, + int x, + int y, + int w); + void create_objects(); + int handle_event(); + MotionMain *plugin; +}; + +class RotationSearchPositions : public BC_PopupMenu +{ +public: + RotationSearchPositions(MotionMain *plugin, + int x, + int y, + int w); + void create_objects(); + int handle_event(); + MotionMain *plugin; +}; class MotionMagnitude : public BC_IPot { public: - MotionMagnitude(MotionMain *plugin, - int x, + MotionMagnitude(MotionMain *plugin, + int x, int y); int handle_event(); MotionMain *plugin; @@ -252,8 +252,8 @@ public: class MotionRMagnitude : public BC_IPot { public: - MotionRMagnitude(MotionMain *plugin, - int x, + MotionRMagnitude(MotionMain *plugin, + int x, int y); int handle_event(); MotionMain *plugin; @@ -262,8 +262,8 @@ public: class MotionReturnSpeed : public BC_IPot { public: - MotionReturnSpeed(MotionMain *plugin, - int x, + MotionReturnSpeed(MotionMain *plugin, + int x, int y); int handle_event(); MotionMain *plugin; @@ -273,8 +273,8 @@ public: class MotionRReturnSpeed : public BC_IPot { public: - MotionRReturnSpeed(MotionMain *plugin, - int x, + MotionRReturnSpeed(MotionMain *plugin, + int x, int y); int handle_event(); MotionMain *plugin; @@ -284,9 +284,9 @@ public: class MotionDrawVectors : public BC_CheckBox { public: - MotionDrawVectors(MotionMain *plugin, + MotionDrawVectors(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionMain *plugin; @@ -296,33 +296,33 @@ public: class AddTrackedFrameOffset : public BC_CheckBox { public: - AddTrackedFrameOffset(MotionMain *plugin, + AddTrackedFrameOffset(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionWindow *gui; MotionMain *plugin; }; -// class MotionGlobal : public BC_CheckBox -// { -// public: -// MotionGlobal(MotionMain *plugin, -// MotionWindow *gui, -// int x, -// int y); -// int handle_event(); -// MotionWindow *gui; -// MotionMain *plugin; -// }; +class MotionGlobal : public BC_CheckBox +{ +public: + MotionGlobal(MotionMain *plugin, + MotionWindow *gui, + int x, + int y); + int handle_event(); + MotionWindow *gui; + MotionMain *plugin; +}; class MotionRotate : public BC_CheckBox { public: - MotionRotate(MotionMain *plugin, + MotionRotate(MotionMain *plugin, MotionWindow *gui, - int x, + int x, int y); int handle_event(); MotionWindow *gui; @@ -353,15 +353,15 @@ public: MotionBlockY *block_y; MotionBlockXText *block_x_text; MotionBlockYText *block_y_text; -// GlobalSearchPositions *global_search_positions; -// RotationSearchPositions *rotation_search_positions; + GlobalSearchPositions *global_search_positions; + RotationSearchPositions *rotation_search_positions; MotionMagnitude *magnitude; MotionRMagnitude *rotate_magnitude; MotionReturnSpeed *return_speed; MotionRReturnSpeed *rotate_return_speed; ActionType *action_type; MotionDrawVectors *vectors; -// MotionGlobal *global; + MotionGlobal *global; MotionRotate *rotate; AddTrackedFrameOffset *addtrackedframeoffset; TrackSingleFrame *track_single; diff --git a/cinelerra-5.1/plugins/motion/motionwindow.inc b/cinelerra-5.1/plugins/motion/motionwindow.inc index 8fbef467..50404d71 100644 --- a/cinelerra-5.1/plugins/motion/motionwindow.inc +++ b/cinelerra-5.1/plugins/motion/motionwindow.inc @@ -2,21 +2,21 @@ /* * CINELERRA * Copyright (C) 2008 Adam Williams - * + * * 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 - * + * */ #ifndef MOTIONWINDOW_INC diff --git a/cinelerra-5.1/plugins/motion/opencvwrapper.C b/cinelerra-5.1/plugins/motion/opencvwrapper.C index 3fadcf0d..7c19be68 100644 --- a/cinelerra-5.1/plugins/motion/opencvwrapper.C +++ b/cinelerra-5.1/plugins/motion/opencvwrapper.C @@ -1,21 +1,21 @@ /* * CINELERRA * Copyright (C) 1997-2012 Adam Williams - * + * * 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 - * + * */ @@ -128,10 +128,10 @@ findPairs( const CvSeq* objectKeypoints, const CvSeq* objectDescriptors, void -flannFindPairs( const CvSeq*, +flannFindPairs( const CvSeq*, const CvSeq* objectDescriptors, - const CvSeq*, - const CvSeq* imageDescriptors, + const CvSeq*, + const CvSeq* imageDescriptors, vector& ptpairs ) { int length = (int)(objectDescriptors->elem_size/sizeof(float)); @@ -171,10 +171,10 @@ flannFindPairs( const CvSeq*, int* indices_ptr = m_indices.ptr(0); float* dists_ptr = m_dists.ptr(0); //printf("flannFindPairs %d m_indices.rows=%d\n", __LINE__, m_indices.rows); - for (int i = 0; i < m_indices.rows; ++i) + for (int i = 0; i < m_indices.rows; ++i) { //printf("flannFindPairs %d dists=%f %f\n", __LINE__, dists_ptr[2 * i], 0.6 * dists_ptr[2 * i + 1]); - if (dists_ptr[2 * i] < 0.6 * dists_ptr[2 * i + 1]) + if (dists_ptr[2 * i] < 0.6 * dists_ptr[2 * i + 1]) { //printf("flannFindPairs %d pairs=%d\n", __LINE__, ptpairs.size()); ptpairs.push_back(i); @@ -185,11 +185,11 @@ flannFindPairs( const CvSeq*, /* a rough implementation for object location */ -int OpenCVWrapper::locatePlanarObject(const CvSeq* objectKeypoints, +int OpenCVWrapper::locatePlanarObject(const CvSeq* objectKeypoints, const CvSeq* objectDescriptors, - const CvSeq* imageKeypoints, + const CvSeq* imageKeypoints, const CvSeq* imageDescriptors, - const CvPoint src_corners[4], + const CvPoint src_corners[4], int *(*point_pairs), int (*total_pairs)) { @@ -199,7 +199,7 @@ int OpenCVWrapper::locatePlanarObject(const CvSeq* objectKeypoints, vector pt1, pt2; CvMat _pt1, _pt2; int i, n; - + (*point_pairs) = 0; (*total_pairs) = 0; @@ -213,8 +213,8 @@ int OpenCVWrapper::locatePlanarObject(const CvSeq* objectKeypoints, // Store keypoints (*point_pairs) = (int*)calloc(ptpairs.size(), sizeof(int)); (*total_pairs) = ptpairs.size() / 2; - - + + for(int i = 0; i < (int)ptpairs.size(); i++) { (*point_pairs)[i] = ptpairs[i]; @@ -292,7 +292,7 @@ OpenCVWrapper::~OpenCVWrapper() int OpenCVWrapper::scan(VFrame *object_frame, VFrame *scene_frame, - int object_x1, + int object_x1, int object_y1, int object_x2, int object_y2, @@ -321,7 +321,7 @@ int OpenCVWrapper::scan(VFrame *object_frame, if(scene_w % QUANTIZE) scene_image_w += QUANTIZE - (scene_w % QUANTIZE); if(scene_h % QUANTIZE) scene_image_h += QUANTIZE - (scene_h % QUANTIZE); - if(object_image && + if(object_image && (object_image_w != this->object_image_w || object_image_h != this->object_image_h)) { @@ -331,7 +331,7 @@ int OpenCVWrapper::scan(VFrame *object_frame, this->object_image_w = object_image_w; this->object_image_h = object_image_h; - if(scene_image && + if(scene_image && (scene_image_w != this->scene_image_w || scene_image_h != this->scene_image_h)) { @@ -345,18 +345,18 @@ int OpenCVWrapper::scan(VFrame *object_frame, if(!object_image) { // Only does greyscale - object_image = cvCreateImage( - cvSize(object_image_w, object_image_h), - 8, + object_image = cvCreateImage( + cvSize(object_image_w, object_image_h), + 8, 1); } if(!scene_image) { // Only does greyscale - scene_image = cvCreateImage( - cvSize(scene_image_w, scene_image_h), - 8, + scene_image = cvCreateImage( + cvSize(scene_image_w, scene_image_h), + 8, 1); } @@ -365,19 +365,19 @@ int OpenCVWrapper::scan(VFrame *object_frame, cvSetImageROI( object_image, cvRect( 0, 0, object_w, object_h ) ); cvSetImageROI( scene_image, cvRect( 0, 0, scene_w, scene_h ) ); - grey_crop((unsigned char*)scene_image->imageData, - scene_frame, - scene_x1, - scene_y1, - scene_x2, + grey_crop((unsigned char*)scene_image->imageData, + scene_frame, + scene_x1, + scene_y1, + scene_x2, scene_y2, scene_image_w, scene_image_h); - grey_crop((unsigned char*)object_image->imageData, - object_frame, - object_x1, - object_y1, - object_x2, + grey_crop((unsigned char*)object_image->imageData, + object_frame, + object_x1, + object_y1, + object_x2, object_y2, object_image_w, object_image_h); @@ -404,11 +404,11 @@ int OpenCVWrapper::scan(VFrame *object_frame, point_pairs = 0; - cvExtractSURF(object_image, - 0, - &object_keypoints, - &object_descriptors, - storage, + cvExtractSURF(object_image, + 0, + &object_keypoints, + &object_descriptors, + storage, params, 0); @@ -418,21 +418,21 @@ int OpenCVWrapper::scan(VFrame *object_frame, // { // CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( object_keypoints, i ); // int size = r1->size / 4; -// draw_rect(frame[object_layer], -// r1->pt.x + object_x1 - size, -// r1->pt.y + object_y1 - size, -// r1->pt.x + object_x1 + size, +// draw_rect(frame[object_layer], +// r1->pt.x + object_x1 - size, +// r1->pt.y + object_y1 - size, +// r1->pt.x + object_x1 + size, // r1->pt.y + object_y1 + size); // } //printf("OpenCVWrapper::process_buffer %d\n", __LINE__); - cvExtractSURF(scene_image, - 0, - &scene_keypoints, - &scene_descriptors, - storage, + cvExtractSURF(scene_image, + 0, + &scene_keypoints, + &scene_descriptors, + storage, params, 0); @@ -441,24 +441,24 @@ int OpenCVWrapper::scan(VFrame *object_frame, // { // CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( scene_keypoints, i ); // int size = r1->size / 4; -// draw_rect(frame[scene_layer], -// r1->pt.x + scene_x1 - size, -// r1->pt.y + scene_y1 - size, -// r1->pt.x + scene_x1 + size, +// draw_rect(frame[scene_layer], +// r1->pt.x + scene_x1 - size, +// r1->pt.y + scene_y1 - size, +// r1->pt.x + scene_x1 + size, // r1->pt.y + scene_y1 + size); // } -// printf("OpenCVWrapper::scan %d %d %d scene keypoints=%d\n", -// __LINE__, +// printf("OpenCVWrapper::scan %d %d %d scene keypoints=%d\n", +// __LINE__, // scene_w, // scene_h, // scene_keypoints->total); - CvPoint src_corners[4] = + CvPoint src_corners[4] = { - { 0, 0 }, - { object_w, 0 }, - { object_w, object_h }, + { 0, 0 }, + { object_w, 0 }, + { object_w, object_h }, { 0, object_h } }; @@ -472,11 +472,11 @@ int OpenCVWrapper::scan(VFrame *object_frame, //printf("OpenCVWrapper::process_buffer %d\n", __LINE__); if(scene_keypoints->total && object_keypoints->total && - locatePlanarObject(object_keypoints, - object_descriptors, - scene_keypoints, - scene_descriptors, - src_corners, + locatePlanarObject(object_keypoints, + object_descriptors, + scene_keypoints, + scene_descriptors, + src_corners, &point_pairs, &total_pairs)) { @@ -493,9 +493,9 @@ int OpenCVWrapper::scan(VFrame *object_frame, // Convert to greyscale & crop -void OpenCVWrapper::grey_crop(unsigned char *dst, - VFrame *src, - int x1, +void OpenCVWrapper::grey_crop(unsigned char *dst, + VFrame *src, + int x1, int y1, int x2, int y2, diff --git a/cinelerra-5.1/plugins/motion/opencvwrapper.h b/cinelerra-5.1/plugins/motion/opencvwrapper.h index 53e0c46b..a33bec7f 100644 --- a/cinelerra-5.1/plugins/motion/opencvwrapper.h +++ b/cinelerra-5.1/plugins/motion/opencvwrapper.h @@ -1,21 +1,21 @@ /* * CINELERRA * Copyright (C) 1997-2012 Adam Williams - * + * * 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 - * + * */ @@ -37,9 +37,9 @@ public: float get_dst_x(int number); float get_dst_y(int number); - void grey_crop(unsigned char *dst, - VFrame *src, - int x1, + void grey_crop(unsigned char *dst, + VFrame *src, + int x1, int y1, int x2, int y2, @@ -49,7 +49,7 @@ public: // Returns 1 when it got something int scan(VFrame *object_frame, VFrame *scene_frame, - int object_x1, + int object_x1, int object_y1, int object_x2, int object_y2, @@ -59,11 +59,11 @@ public: int scene_y2); private: - int locatePlanarObject(const CvSeq* objectKeypoints, + int locatePlanarObject(const CvSeq* objectKeypoints, const CvSeq* objectDescriptors, - const CvSeq* imageKeypoints, + const CvSeq* imageKeypoints, const CvSeq* imageDescriptors, - const CvPoint src_corners[4], + const CvPoint src_corners[4], int *(*point_pairs), int (*total_pairs)); diff --git a/cinelerra-5.1/plugins/motion/rotatescan.C b/cinelerra-5.1/plugins/motion/rotatescan.C deleted file mode 100644 index e7b346e9..00000000 --- a/cinelerra-5.1/plugins/motion/rotatescan.C +++ /dev/null @@ -1,471 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2016 Adam Williams - * - * 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 "affine.h" -#include "bcsignals.h" -#include "clip.h" -#include "motionscan.h" -#include "rotatescan.h" -#include "motion.h" -#include "mutex.h" -#include "vframe.h" - - - - - - - - - -RotateScanPackage::RotateScanPackage() -{ -} - - -RotateScanUnit::RotateScanUnit(RotateScan *server, MotionMain *plugin) - : LoadClient(server) -{ - this->server = server; - this->plugin = plugin; - rotater = 0; - temp = 0; -} - -RotateScanUnit::~RotateScanUnit() -{ - delete rotater; - delete temp; -} - -void RotateScanUnit::process_package(LoadPackage *package) -{ - if(server->skip) return; - RotateScanPackage *pkg = (RotateScanPackage*)package; - - if((pkg->difference = server->get_cache(pkg->angle)) < 0) - { -//printf("RotateScanUnit::process_package %d\n", __LINE__); - int color_model = server->previous_frame->get_color_model(); - int pixel_size = BC_CModels::calculate_pixelsize(color_model); - int row_bytes = server->previous_frame->get_bytes_per_line(); - - if(!rotater) - rotater = new AffineEngine(1, 1); - if(!temp) temp = new VFrame(0, - -1, - server->previous_frame->get_w(), - server->previous_frame->get_h(), - color_model, - -1); -//printf("RotateScanUnit::process_package %d\n", __LINE__); - - -// Rotate original block size -// rotater->set_viewport(server->block_x1, -// server->block_y1, -// server->block_x2 - server->block_x1, -// server->block_y2 - server->block_y1); - rotater->set_in_viewport(server->block_x1, - server->block_y1, - server->block_x2 - server->block_x1, - server->block_y2 - server->block_y1); - rotater->set_out_viewport(server->block_x1, - server->block_y1, - server->block_x2 - server->block_x1, - server->block_y2 - server->block_y1); -// rotater->set_pivot(server->block_x, server->block_y); - rotater->set_in_pivot(server->block_x, server->block_y); - rotater->set_out_pivot(server->block_x, server->block_y); -//printf("RotateScanUnit::process_package %d\n", __LINE__); - rotater->rotate(temp, - server->previous_frame, - pkg->angle); - -// Scan reduced block size -//plugin->output_frame->copy_from(server->current_frame); -//plugin->output_frame->copy_from(temp); -// printf("RotateScanUnit::process_package %d %d %d %d %d\n", -// __LINE__, -// server->scan_x, -// server->scan_y, -// server->scan_w, -// server->scan_h); -// Clamp coordinates - int x1 = server->scan_x; - int y1 = server->scan_y; - int x2 = x1 + server->scan_w; - int y2 = y1 + server->scan_h; - x2 = MIN(temp->get_w(), x2); - y2 = MIN(temp->get_h(), y2); - x2 = MIN(server->current_frame->get_w(), x2); - y2 = MIN(server->current_frame->get_h(), y2); - x1 = MAX(0, x1); - y1 = MAX(0, y1); - - if(x2 > x1 && y2 > y1) - { - pkg->difference = MotionScan::abs_diff( - temp->get_rows()[y1] + x1 * pixel_size, - server->current_frame->get_rows()[y1] + x1 * pixel_size, - row_bytes, - x2 - x1, - y2 - y1, - color_model); -//printf("RotateScanUnit::process_package %d\n", __LINE__); - server->put_cache(pkg->angle, pkg->difference); - } - -// printf("RotateScanUnit::process_package 10 x=%d y=%d w=%d h=%d block_x=%d block_y=%d angle=%f scan_w=%d scan_h=%d diff=%lld\n", -// server->block_x1, -// server->block_y1, -// server->block_x2 - server->block_x1, -// server->block_y2 - server->block_y1, -// server->block_x, -// server->block_y, -// pkg->angle, -// server->scan_w, -// server->scan_h, -// pkg->difference); - } -} - - - - - - - - - - - - - - - - - - - - - - -RotateScan::RotateScan(MotionMain *plugin, - int total_clients, - int total_packages) - : LoadServer( -//1, 1 -total_clients, total_packages -) -{ - this->plugin = plugin; - cache_lock = new Mutex("RotateScan::cache_lock"); -} - - -RotateScan::~RotateScan() -{ - delete cache_lock; -} - -void RotateScan::init_packages() -{ - for(int i = 0; i < get_total_packages(); i++) - { - RotateScanPackage *pkg = (RotateScanPackage*)get_package(i); - pkg->angle = i * - (scan_angle2 - scan_angle1) / - (total_steps - 1) + - scan_angle1; - } -} - -LoadClient* RotateScan::new_client() -{ - return new RotateScanUnit(this, plugin); -} - -LoadPackage* RotateScan::new_package() -{ - return new RotateScanPackage; -} - - -float RotateScan::scan_frame(VFrame *previous_frame, - VFrame *current_frame, - int block_x, - int block_y) -{ - skip = 0; - this->block_x = block_x; - this->block_y = block_y; - -//printf("RotateScan::scan_frame %d\n", __LINE__); - switch(plugin->config.tracking_type) - { - case MotionScan::NO_CALCULATE: - result = plugin->config.rotation_center; - skip = 1; - break; - - case MotionScan::LOAD: - { - char string[BCTEXTLEN]; - sprintf(string, - "%s%06ld", - ROTATION_FILE, - plugin->get_source_position()); - FILE *input = fopen(string, "r"); - if(input) - { - int temp = fscanf(input, "%f", &result); - fclose(input); - skip = 1; - } - else - { - perror("RotateScan::scan_frame LOAD"); - } - break; - } - } - - - - - - - - - this->previous_frame = previous_frame; - this->current_frame = current_frame; - int w = current_frame->get_w(); - int h = current_frame->get_h(); - int block_w = w * plugin->config.global_block_w / 100; - int block_h = h * plugin->config.global_block_h / 100; - - if(this->block_x - block_w / 2 < 0) block_w = this->block_x * 2; - if(this->block_y - block_h / 2 < 0) block_h = this->block_y * 2; - if(this->block_x + block_w / 2 > w) block_w = (w - this->block_x) * 2; - if(this->block_y + block_h / 2 > h) block_h = (h - this->block_y) * 2; - - block_x1 = this->block_x - block_w / 2; - block_x2 = this->block_x + block_w / 2; - block_y1 = this->block_y - block_h / 2; - block_y2 = this->block_y + block_h / 2; - - -// Calculate the maximum area available to scan after rotation. -// Must be calculated from the starting range because of cache. -// Get coords of rectangle after rotation. - double center_x = this->block_x; - double center_y = this->block_y; - double max_angle = plugin->config.rotation_range; - double base_angle1 = atan((float)block_h / block_w); - double base_angle2 = atan((float)block_w / block_h); - double target_angle1 = base_angle1 + max_angle * 2 * M_PI / 360; - double target_angle2 = base_angle2 + max_angle * 2 * M_PI / 360; - double radius = sqrt(block_w * block_w + block_h * block_h) / 2; - double x1 = center_x - cos(target_angle1) * radius; - double y1 = center_y - sin(target_angle1) * radius; - double x2 = center_x + sin(target_angle2) * radius; - double y2 = center_y - cos(target_angle2) * radius; - double x3 = center_x - sin(target_angle2) * radius; - double y3 = center_y + cos(target_angle2) * radius; - -// Track top edge to find greatest area. - double max_area1 = 0; - double max_x1 = 0; - double max_y1 = 0; - for(double x = x1; x < x2; x++) - { - double y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); - if(x >= center_x && x < block_x2 && y >= block_y1 && y < center_y) - { - double area = fabs(x - center_x) * fabs(y - center_y); - if(area > max_area1) - { - max_area1 = area; - max_x1 = x; - max_y1 = y; - } - } - } - -// Track left edge to find greatest area. - double max_area2 = 0; - double max_x2 = 0; - double max_y2 = 0; - for(double y = y1; y < y3; y++) - { - double x = x1 + (x3 - x1) * (y - y1) / (y3 - y1); - if(x >= block_x1 && x < center_x && y >= block_y1 && y < center_y) - { - double area = fabs(x - center_x) * fabs(y - center_y); - if(area > max_area2) - { - max_area2 = area; - max_x2 = x; - max_y2 = y; - } - } - } - - double max_x, max_y; - max_x = max_x2; - max_y = max_y1; - -// Get reduced scan coords - scan_w = (int)(fabs(max_x - center_x) * 2); - scan_h = (int)(fabs(max_y - center_y) * 2); - scan_x = (int)(center_x - scan_w / 2); - scan_y = (int)(center_y - scan_h / 2); -// printf("RotateScan::scan_frame center=%d,%d scan=%d,%d %dx%d\n", -// this->block_x, this->block_y, scan_x, scan_y, scan_w, scan_h); -// printf(" angle_range=%f block= %d,%d,%d,%d\n", max_angle, block_x1, block_y1, block_x2, block_y2); - -// Determine min angle from size of block - double angle1 = atan((double)block_h / block_w); - double angle2 = atan((double)(block_h - 1) / (block_w + 1)); - double min_angle = fabs(angle2 - angle1) / OVERSAMPLE; - min_angle = MAX(min_angle, MIN_ANGLE); - -//printf("RotateScan::scan_frame %d min_angle=%f\n", __LINE__, min_angle * 360 / 2 / M_PI); - - cache.remove_all_objects(); - - - if(!skip) - { - if(previous_frame->data_matches(current_frame)) - { -//printf("RotateScan::scan_frame: frames match. Skipping.\n"); - result = plugin->config.rotation_center; - skip = 1; - } - } - - if(!skip) - { -// Initial search range - float angle_range = max_angle; - result = plugin->config.rotation_center; - total_steps = plugin->config.rotate_positions; - - - while(angle_range >= min_angle * total_steps) - { - scan_angle1 = result - angle_range; - scan_angle2 = result + angle_range; - - - set_package_count(total_steps); -//set_package_count(1); - process_packages(); - - int64_t min_difference = -1; - for(int i = 0; i < get_total_packages(); i++) - { - RotateScanPackage *pkg = (RotateScanPackage*)get_package(i); - if(pkg->difference < min_difference || min_difference == -1) - { - min_difference = pkg->difference; - result = pkg->angle; - } -//break; - } - - angle_range /= 2; - -//break; - } - } - -//printf("RotateScan::scan_frame %d\n", __LINE__); - - if(!skip && plugin->config.tracking_type == MotionScan::SAVE) - { - char string[BCTEXTLEN]; - sprintf(string, - "%s%06ld", - ROTATION_FILE, - plugin->get_source_position()); - FILE *output = fopen(string, "w"); - if(output) - { - fprintf(output, "%f\n", result); - fclose(output); - } - else - { - perror("RotateScan::scan_frame SAVE"); - } - } - -//printf("RotateScan::scan_frame %d angle=%f\n", __LINE__, result); - - - - return result; -} - -int64_t RotateScan::get_cache(float angle) -{ - int64_t result = -1; - cache_lock->lock("RotateScan::get_cache"); - for(int i = 0; i < cache.total; i++) - { - RotateScanCache *ptr = cache.values[i]; - if(fabs(ptr->angle - angle) <= MIN_ANGLE) - { - result = ptr->difference; - break; - } - } - cache_lock->unlock(); - return result; -} - -void RotateScan::put_cache(float angle, int64_t difference) -{ - RotateScanCache *ptr = new RotateScanCache(angle, difference); - cache_lock->lock("RotateScan::put_cache"); - cache.append(ptr); - cache_lock->unlock(); -} - - - - - - - - - -RotateScanCache::RotateScanCache(float angle, int64_t difference) -{ - this->angle = angle; - this->difference = difference; -} - - - diff --git a/cinelerra-5.1/plugins/motion/rotatescan.h b/cinelerra-5.1/plugins/motion/rotatescan.h deleted file mode 100644 index 27001e34..00000000 --- a/cinelerra-5.1/plugins/motion/rotatescan.h +++ /dev/null @@ -1,136 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2016 Adam Williams - * - * 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 - * - */ - - - - -#ifndef ROTATESCAN_H -#define ROTATESCAN_H - - - -#include "affine.inc" -#include "loadbalance.h" -#include "motion.inc" -#include "vframe.inc" -#include - -class RotateScan; - - -class RotateScanPackage : public LoadPackage -{ -public: - RotateScanPackage(); - float angle; - int64_t difference; -}; - -class RotateScanCache -{ -public: - RotateScanCache(float angle, int64_t difference); - float angle; - int64_t difference; -}; - -class RotateScanUnit : public LoadClient -{ -public: - RotateScanUnit(RotateScan *server, MotionMain *plugin); - ~RotateScanUnit(); - - void process_package(LoadPackage *package); - - RotateScan *server; - MotionMain *plugin; - AffineEngine *rotater; - VFrame *temp; -}; - -class RotateScan : public LoadServer -{ -public: - RotateScan(MotionMain *plugin, - int total_clients, - int total_packages); - ~RotateScan(); - - friend class RotateScanUnit; - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - -// Invoke the motion engine for a search -// Frame before rotation - float scan_frame(VFrame *previous_frame, -// Frame after rotation - VFrame *current_frame, -// Pivot - int block_x, - int block_y); - int64_t get_cache(float angle); - void put_cache(float angle, int64_t difference); - - -// Angle result - float result; - -private: - VFrame *previous_frame; -// Frame after motion - VFrame *current_frame; - - MotionMain *plugin; - int skip; - -// Pivot - int block_x; - int block_y; -// Block to rotate - int block_x1; - int block_x2; - int block_y1; - int block_y2; -// Area to compare - int scan_x; - int scan_y; - int scan_w; - int scan_h; -// Range of angles to compare - float scan_angle1, scan_angle2; - int total_steps; - - ArrayList cache; - Mutex *cache_lock; -}; - - - - - -#endif - - - - - diff --git a/cinelerra-5.1/plugins/motion/rotatescan.inc b/cinelerra-5.1/plugins/motion/rotatescan.inc deleted file mode 100644 index d3dfd975..00000000 --- a/cinelerra-5.1/plugins/motion/rotatescan.inc +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef ROTATESCAN_INC -#define ROTATESCAN_INC - - -class RotateScan; - - -#endif - - - - diff --git a/cinelerra-5.1/plugins/motion2point/Makefile b/cinelerra-5.1/plugins/motion2point/Makefile index 914cf00d..5a00398c 100644 --- a/cinelerra-5.1/plugins/motion2point/Makefile +++ b/cinelerra-5.1/plugins/motion2point/Makefile @@ -2,15 +2,17 @@ include ../../plugin_defs OBJS := \ $(OBJDIR)/downsampleengine.o \ - $(OBJDIR)/motionscan.o \ + $(OBJDIR)/motionscan-hv.o \ $(OBJDIR)/motion.o \ $(OBJDIR)/motionwindow.o +CFLAGS += -DMotionScan=MotionHVScan + PLUGIN = motion2 include ../../plugin_config $(OBJDIR)/downsampleengine.o: downsampleengine.C $(OBJDIR)/motion.o: motion.C -$(OBJDIR)/motionscan.o: motionscan.C +$(OBJDIR)/motionscan-hv.o: motionscan-hv.C $(OBJDIR)/motionwindow.o: motionwindow.C diff --git a/cinelerra-5.1/plugins/motion2point/motion.C b/cinelerra-5.1/plugins/motion2point/motion.C index 28c09378..ad745c4f 100644 --- a/cinelerra-5.1/plugins/motion2point/motion.C +++ b/cinelerra-5.1/plugins/motion2point/motion.C @@ -20,7 +20,7 @@ */ #include "affine.h" -#include "../motion/motionscan.h" +#include "../motion-hv/motionscan-hv.h" #include "bcdisplayinfo.h" #include "bcsignals.h" #include "clip.h" diff --git a/cinelerra-5.1/plugins/motion2point/motion.h b/cinelerra-5.1/plugins/motion2point/motion.h index 0fd65948..19d1fa65 100644 --- a/cinelerra-5.1/plugins/motion2point/motion.h +++ b/cinelerra-5.1/plugins/motion2point/motion.h @@ -27,7 +27,7 @@ #include #include "affine.inc" -#include "motionscan.inc" +#include "motionscan-hv.inc" #include "bchash.inc" #include "filexml.inc" #include "keyframe.inc" diff --git a/cinelerra-5.1/plugins/motion2point/motionscan-hv.C b/cinelerra-5.1/plugins/motion2point/motionscan-hv.C new file mode 120000 index 00000000..898c188d --- /dev/null +++ b/cinelerra-5.1/plugins/motion2point/motionscan-hv.C @@ -0,0 +1 @@ +../motion-hv/motionscan-hv.C \ No newline at end of file diff --git a/cinelerra-5.1/plugins/motion2point/motionscan-hv.h b/cinelerra-5.1/plugins/motion2point/motionscan-hv.h new file mode 120000 index 00000000..d5eb987c --- /dev/null +++ b/cinelerra-5.1/plugins/motion2point/motionscan-hv.h @@ -0,0 +1 @@ +../motion-hv/motionscan-hv.h \ No newline at end of file diff --git a/cinelerra-5.1/plugins/motion2point/motionscan-hv.inc b/cinelerra-5.1/plugins/motion2point/motionscan-hv.inc new file mode 120000 index 00000000..4c59354a --- /dev/null +++ b/cinelerra-5.1/plugins/motion2point/motionscan-hv.inc @@ -0,0 +1 @@ +../motion-hv/motionscan-hv.inc \ No newline at end of file diff --git a/cinelerra-5.1/plugins/motion2point/motionscan.C b/cinelerra-5.1/plugins/motion2point/motionscan.C deleted file mode 120000 index 4ac14722..00000000 --- a/cinelerra-5.1/plugins/motion2point/motionscan.C +++ /dev/null @@ -1 +0,0 @@ -../motion/motionscan.C \ No newline at end of file diff --git a/cinelerra-5.1/plugins/motion2point/motionscan.h b/cinelerra-5.1/plugins/motion2point/motionscan.h deleted file mode 120000 index 9461913f..00000000 --- a/cinelerra-5.1/plugins/motion2point/motionscan.h +++ /dev/null @@ -1 +0,0 @@ -../motion/motionscan.h \ No newline at end of file diff --git a/cinelerra-5.1/plugins/motion2point/motionscan.inc b/cinelerra-5.1/plugins/motion2point/motionscan.inc deleted file mode 120000 index e4b8d557..00000000 --- a/cinelerra-5.1/plugins/motion2point/motionscan.inc +++ /dev/null @@ -1 +0,0 @@ -../motion/motionscan.inc \ No newline at end of file diff --git a/cinelerra-5.1/plugins/motion2point/motionwindow.C b/cinelerra-5.1/plugins/motion2point/motionwindow.C index ad959d8c..ccfbe504 100644 --- a/cinelerra-5.1/plugins/motion2point/motionwindow.C +++ b/cinelerra-5.1/plugins/motion2point/motionwindow.C @@ -24,7 +24,7 @@ #include "clip.h" #include "language.h" #include "motion.h" -#include "motionscan.h" +#include "motionscan-hv.h" #include "motionwindow.h" diff --git a/cinelerra-5.1/thirdparty/Makefile b/cinelerra-5.1/thirdparty/Makefile index a7e7cd63..c7cc7f3c 100644 --- a/cinelerra-5.1/thirdparty/Makefile +++ b/cinelerra-5.1/thirdparty/Makefile @@ -160,7 +160,7 @@ a52dec.mak_params?= ; cd $(call bld_path,a52dec,include); ln -sf . a52dec a52dec.cfg_vars?= CFLAGS+=" -U__FreeBSD__ $(call inc_path,djbfft)" LIBS+=" $(call ld_path,djbfft)" a52dec.cfg_params?=--enable-djbfft djbfft.cfg_vars?=echo "$(call bld_path,djbfft)" > conf-home; \ - (CFLAGS="$(CFLAGS)"; $(CFG_VARS); echo "$(CC) $$$$CFLAGS") > conf-cc; \ + (CFLAGS="$(CFLAGS)"; $(CFG_VARS)$(if $(CFG_VARS),; )echo "$(CC) $$$$CFLAGS") > conf-cc; \ echo > ./configure; chmod +x ./configure; djbfft.mak_params?=; cd $(call bld_path,djbfft); ln -sf djbfft.a libdjbfft.a audiofile.cfg_params?=--enable-shared=no