aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-01-14 04:49:22 +0100
committerMichael Niedermayer <michaelni@gmx.at>2011-01-20 00:49:27 +0100
commite4852fb38df0c3a43e19b5a74c44f8ea57e98951 (patch)
tree6b3d1a2238982e269241e0343aa5865d509e74d3
parentfe678413557a3bcc4639897f7f8c30f61cc8fc31 (diff)
downloadffmpeg-e4852fb38df0c3a43e19b5a74c44f8ea57e98951.tar.gz
Add MPlayers libmpcodecs, this will be needed for our libavfilter wraper for it.
-rw-r--r--libavfilter/libmpcodecs/cpudetect.h59
-rw-r--r--libavfilter/libmpcodecs/help_mp.h2136
-rw-r--r--libavfilter/libmpcodecs/img_format.c170
-rw-r--r--libavfilter/libmpcodecs/img_format.h214
-rw-r--r--libavfilter/libmpcodecs/libvo/fastmemcpy.h99
-rw-r--r--libavfilter/libmpcodecs/libvo/video_out.h287
-rw-r--r--libavfilter/libmpcodecs/mp_image.c200
-rw-r--r--libavfilter/libmpcodecs/mp_image.h137
-rw-r--r--libavfilter/libmpcodecs/mp_msg.h164
-rw-r--r--libavfilter/libmpcodecs/mpbswap.h38
-rw-r--r--libavfilter/libmpcodecs/mpc_info.h43
-rw-r--r--libavfilter/libmpcodecs/pullup.c822
-rw-r--r--libavfilter/libmpcodecs/pullup.h102
-rw-r--r--libavfilter/libmpcodecs/vd_ffmpeg.h24
-rw-r--r--libavfilter/libmpcodecs/vf.h169
-rw-r--r--libavfilter/libmpcodecs/vf_2xsai.c336
-rw-r--r--libavfilter/libmpcodecs/vf_blackframe.c148
-rw-r--r--libavfilter/libmpcodecs/vf_boxblur.c214
-rw-r--r--libavfilter/libmpcodecs/vf_cropdetect.c201
-rw-r--r--libavfilter/libmpcodecs/vf_decimate.c198
-rw-r--r--libavfilter/libmpcodecs/vf_delogo.c262
-rw-r--r--libavfilter/libmpcodecs/vf_denoise3d.c268
-rw-r--r--libavfilter/libmpcodecs/vf_detc.c453
-rw-r--r--libavfilter/libmpcodecs/vf_dint.c214
-rw-r--r--libavfilter/libmpcodecs/vf_divtc.c720
-rw-r--r--libavfilter/libmpcodecs/vf_down3dright.c166
-rw-r--r--libavfilter/libmpcodecs/vf_dsize.c123
-rw-r--r--libavfilter/libmpcodecs/vf_eq.c258
-rw-r--r--libavfilter/libmpcodecs/vf_eq2.c519
-rw-r--r--libavfilter/libmpcodecs/vf_field.c89
-rw-r--r--libavfilter/libmpcodecs/vf_fil.c116
-rw-r--r--libavfilter/libmpcodecs/vf_filmdint.c1461
-rw-r--r--libavfilter/libmpcodecs/vf_fixpts.c137
-rw-r--r--libavfilter/libmpcodecs/vf_framestep.c205
-rw-r--r--libavfilter/libmpcodecs/vf_fspp.c2117
-rw-r--r--libavfilter/libmpcodecs/vf_geq.c197
-rw-r--r--libavfilter/libmpcodecs/vf_gradfun.c411
-rw-r--r--libavfilter/libmpcodecs/vf_harddup.c92
-rw-r--r--libavfilter/libmpcodecs/vf_hqdn3d.c373
-rw-r--r--libavfilter/libmpcodecs/vf_hue.c200
-rw-r--r--libavfilter/libmpcodecs/vf_il.c148
-rw-r--r--libavfilter/libmpcodecs/vf_ilpack.c453
-rw-r--r--libavfilter/libmpcodecs/vf_ivtc.c550
-rw-r--r--libavfilter/libmpcodecs/vf_kerndeint.c345
-rw-r--r--libavfilter/libmpcodecs/vf_mcdeint.c338
-rw-r--r--libavfilter/libmpcodecs/vf_mirror.c131
-rw-r--r--libavfilter/libmpcodecs/vf_noise.c474
-rw-r--r--libavfilter/libmpcodecs/vf_ow.c322
-rw-r--r--libavfilter/libmpcodecs/vf_palette.c235
-rw-r--r--libavfilter/libmpcodecs/vf_perspective.c343
-rw-r--r--libavfilter/libmpcodecs/vf_phase.c301
-rw-r--r--libavfilter/libmpcodecs/vf_pp7.c491
-rw-r--r--libavfilter/libmpcodecs/vf_pullup.c314
-rw-r--r--libavfilter/libmpcodecs/vf_qp.c177
-rw-r--r--libavfilter/libmpcodecs/vf_rectangle.c181
-rw-r--r--libavfilter/libmpcodecs/vf_remove_logo.c906
-rw-r--r--libavfilter/libmpcodecs/vf_rgbtest.c171
-rw-r--r--libavfilter/libmpcodecs/vf_rotate.c152
-rw-r--r--libavfilter/libmpcodecs/vf_sab.c321
-rw-r--r--libavfilter/libmpcodecs/vf_scale.h35
-rw-r--r--libavfilter/libmpcodecs/vf_screenshot.c322
-rw-r--r--libavfilter/libmpcodecs/vf_smartblur.c262
-rw-r--r--libavfilter/libmpcodecs/vf_softpulldown.c164
-rw-r--r--libavfilter/libmpcodecs/vf_softskip.c102
-rw-r--r--libavfilter/libmpcodecs/vf_spp.c620
-rw-r--r--libavfilter/libmpcodecs/vf_swapuv.c106
-rw-r--r--libavfilter/libmpcodecs/vf_telecine.c155
-rw-r--r--libavfilter/libmpcodecs/vf_test.c333
-rw-r--r--libavfilter/libmpcodecs/vf_tile.c330
-rw-r--r--libavfilter/libmpcodecs/vf_tinterlace.c235
-rw-r--r--libavfilter/libmpcodecs/vf_unsharp.c324
-rw-r--r--libavfilter/libmpcodecs/vf_uspp.c385
-rw-r--r--libavfilter/libmpcodecs/vf_yuvcsp.c120
-rw-r--r--libavfilter/libmpcodecs/vf_yvu9.c105
-rw-r--r--libavfilter/libmpcodecs/vfcap.h56
75 files changed, 24149 insertions, 0 deletions
diff --git a/libavfilter/libmpcodecs/cpudetect.h b/libavfilter/libmpcodecs/cpudetect.h
new file mode 100644
index 0000000000..0f433e707c
--- /dev/null
+++ b/libavfilter/libmpcodecs/cpudetect.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_CPUDETECT_H
+#define MPLAYER_CPUDETECT_H
+
+//#include "config.h"
+
+#define CPUTYPE_I386 3
+#define CPUTYPE_I486 4
+#define CPUTYPE_I586 5
+#define CPUTYPE_I686 6
+
+#include "libavutil/x86_cpu.h"
+
+typedef struct cpucaps_s {
+ int cpuType;
+ int cpuModel;
+ int cpuStepping;
+ int hasMMX;
+ int hasMMX2;
+ int has3DNow;
+ int has3DNowExt;
+ int hasSSE;
+ int hasSSE2;
+ int hasSSE3;
+ int hasSSSE3;
+ int hasSSE4a;
+ int isX86;
+ unsigned cl_size; /* size of cache line */
+ int hasAltiVec;
+ int hasTSC;
+} CpuCaps;
+
+extern CpuCaps gCpuCaps;
+
+void do_cpuid(unsigned int ax, unsigned int *p);
+
+void GetCpuCaps(CpuCaps *caps);
+
+/* returned value is malloc()'ed so free() it after use */
+char *GetCpuFriendlyName(unsigned int regs[], unsigned int regs2[]);
+
+#endif /* MPLAYER_CPUDETECT_H */
diff --git a/libavfilter/libmpcodecs/help_mp.h b/libavfilter/libmpcodecs/help_mp.h
new file mode 100644
index 0000000000..87b828d933
--- /dev/null
+++ b/libavfilter/libmpcodecs/help_mp.h
@@ -0,0 +1,2136 @@
+/* WARNING! This is a generated file, do NOT edit.
+ * See the help/ subdirectory for the editable files. */
+
+#ifndef MPLAYER_HELP_MP_H
+#define MPLAYER_HELP_MP_H
+
+// $Revision: 32397 $
+// MASTER FILE. Use this file as base for translations.
+// Translated files should be sent to the mplayer-DOCS mailing list or
+// to the help messages maintainer, see DOCS/tech/MAINTAINERS.
+// The header of the translated file should contain credits and contact
+// information. Before major releases we will notify all translators to update
+// their files. Please do not simply translate and forget this, outdated
+// translations quickly become worthless. To help us spot outdated files put a
+// note like "sync'ed with help_mp-en.h XXX" in the header of the translation.
+// Do NOT translate the above lines, just follow the instructions.
+
+
+// ========================= MPlayer help ===========================
+
+static const char help_text[]=
+"Usage: mplayer [options] [url|path/]filename\n"
+"\n"
+"Basic options: (complete list in the man page)\n"
+" -vo <drv> select video output driver ('-vo help' for a list)\n"
+" -ao <drv> select audio output driver ('-ao help' for a list)\n"
+#ifdef CONFIG_VCD
+" vcd://<trackno> play (S)VCD (Super Video CD) track (raw device, no mount)\n"
+#endif
+#ifdef CONFIG_DVDREAD
+" dvd://<titleno> play DVD title from device instead of plain file\n"
+#endif
+" -alang/-slang select DVD audio/subtitle language (by 2-char country code)\n"
+" -ss <position> seek to given (seconds or hh:mm:ss) position\n"
+" -nosound do not play sound\n"
+" -fs fullscreen playback (or -vm, -zoom, details in the man page)\n"
+" -x <x> -y <y> set display resolution (for use with -vm or -zoom)\n"
+" -sub <file> specify subtitle file to use (also see -subfps, -subdelay)\n"
+" -playlist <file> specify playlist file\n"
+" -vid x -aid y select video (x) and audio (y) stream to play\n"
+" -fps x -srate y change video (x fps) and audio (y Hz) rate\n"
+" -pp <quality> enable postprocessing filter (details in the man page)\n"
+" -framedrop enable frame dropping (for slow machines)\n"
+"\n"
+"Basic keys: (complete list in the man page, also check input.conf)\n"
+" <- or -> seek backward/forward 10 seconds\n"
+" down or up seek backward/forward 1 minute\n"
+" pgdown or pgup seek backward/forward 10 minutes\n"
+" < or > step backward/forward in playlist\n"
+" p or SPACE pause movie (press any key to continue)\n"
+" q or ESC stop playing and quit program\n"
+" + or - adjust audio delay by +/- 0.1 second\n"
+" o cycle OSD mode: none / seekbar / seekbar + timer\n"
+" * or / increase or decrease PCM volume\n"
+" x or z adjust subtitle delay by +/- 0.1 second\n"
+" r or t adjust subtitle position up/down, also see -vf expand\n"
+"\n"
+" * * * SEE THE MAN PAGE FOR DETAILS, FURTHER (ADVANCED) OPTIONS AND KEYS * * *\n"
+"\n";
+
+// ========================= MPlayer messages ===========================
+
+// mplayer.c
+#define MSGTR_Exiting "\nExiting...\n"
+#define MSGTR_ExitingHow "\nExiting... (%s)\n"
+#define MSGTR_Exit_quit "Quit"
+#define MSGTR_Exit_eof "End of file"
+#define MSGTR_Exit_error "Fatal error"
+#define MSGTR_IntBySignal "\nMPlayer interrupted by signal %d in module: %s\n"
+#define MSGTR_NoHomeDir "Cannot find HOME directory.\n"
+#define MSGTR_GetpathProblem "get_path(\"config\") problem\n"
+#define MSGTR_CreatingCfgFile "Creating config file: %s\n"
+#define MSGTR_BuiltinCodecsConf "Using built-in default codecs.conf.\n"
+#define MSGTR_CantLoadFont "Cannot load bitmap font: %s\n"
+#define MSGTR_CantLoadSub "Cannot load subtitles: %s\n"
+#define MSGTR_DumpSelectedStreamMissing "dump: FATAL: Selected stream missing!\n"
+#define MSGTR_CantOpenDumpfile "Cannot open dump file.\n"
+#define MSGTR_CoreDumped "Core dumped ;)\n"
+#define MSGTR_FPSnotspecified "FPS not specified in the header or invalid, use the -fps option.\n"
+#define MSGTR_TryForceAudioFmtStr "Trying to force audio codec driver family %s...\n"
+#define MSGTR_CantFindAudioCodec "Cannot find codec for audio format 0x%X.\n"
+#define MSGTR_TryForceVideoFmtStr "Trying to force video codec driver family %s...\n"
+#define MSGTR_CantFindVideoCodec "Cannot find codec matching selected -vo and video format 0x%X.\n"
+#define MSGTR_CannotInitVO "FATAL: Cannot initialize video driver.\n"
+#define MSGTR_CannotInitAO "Could not open/initialize audio device -> no sound.\n"
+#define MSGTR_StartPlaying "Starting playback...\n"
+
+#define MSGTR_SystemTooSlow "\n\n"\
+" ************************************************\n"\
+" **** Your system is too SLOW to play this! ****\n"\
+" ************************************************\n\n"\
+"Possible reasons, problems, workarounds:\n"\
+"- Most common: broken/buggy _audio_ driver\n"\
+" - Try -ao sdl or use the OSS emulation of ALSA.\n"\
+" - Experiment with different values for -autosync, 30 is a good start.\n"\
+"- Slow video output\n"\
+" - Try a different -vo driver (-vo help for a list) or try -framedrop!\n"\
+"- Slow CPU\n"\
+" - Don't try to play a big DVD/DivX on a slow CPU! Try some of the lavdopts,\n"\
+" e.g. -vfm ffmpeg -lavdopts lowres=1:fast:skiploopfilter=all.\n"\
+"- Broken file\n"\
+" - Try various combinations of -nobps -ni -forceidx -mc 0.\n"\
+"- Slow media (NFS/SMB mounts, DVD, VCD etc)\n"\
+" - Try -cache 8192.\n"\
+"- Are you using -cache to play a non-interleaved AVI file?\n"\
+" - Try -nocache.\n"\
+"Read DOCS/HTML/en/video.html for tuning/speedup tips.\n"\
+"If none of this helps you, read DOCS/HTML/en/bugreports.html.\n\n"
+
+#define MSGTR_NoGui "MPlayer was compiled WITHOUT GUI support.\n"
+#define MSGTR_GuiNeedsX "MPlayer GUI requires X11.\n"
+#define MSGTR_Playing "\nPlaying %s.\n"
+#define MSGTR_NoSound "Audio: no sound\n"
+#define MSGTR_FPSforced "FPS forced to be %5.3f (ftime: %5.3f).\n"
+#define MSGTR_CompiledWithRuntimeDetection "Compiled with runtime CPU detection.\n"
+#define MSGTR_CompiledWithCPUExtensions "Compiled for x86 CPU with extensions:"
+#define MSGTR_AvailableVideoOutputDrivers "Available video output drivers:\n"
+#define MSGTR_AvailableAudioOutputDrivers "Available audio output drivers:\n"
+#define MSGTR_AvailableAudioCodecs "Available audio codecs:\n"
+#define MSGTR_AvailableVideoCodecs "Available video codecs:\n"
+#define MSGTR_AvailableAudioFm "Available (compiled-in) audio codec families/drivers:\n"
+#define MSGTR_AvailableVideoFm "Available (compiled-in) video codec families/drivers:\n"
+#define MSGTR_AvailableFsType "Available fullscreen layer change modes:\n"
+#define MSGTR_UsingRTCTiming "Using Linux hardware RTC timing (%ldHz).\n"
+#define MSGTR_CannotReadVideoProperties "Video: Cannot read properties.\n"
+#define MSGTR_NoStreamFound "No stream found.\n"
+#define MSGTR_ErrorInitializingVODevice "Error opening/initializing the selected video_out (-vo) device.\n"
+#define MSGTR_ForcedVideoCodec "Forced video codec: %s\n"
+#define MSGTR_ForcedAudioCodec "Forced audio codec: %s\n"
+#define MSGTR_Video_NoVideo "Video: no video\n"
+#define MSGTR_NotInitializeVOPorVO "\nFATAL: Could not initialize video filters (-vf) or video output (-vo).\n"
+#define MSGTR_Paused "\n ===== PAUSE =====\r" // no more than 23 characters (status line for audio files)
+#define MSGTR_PlaylistLoadUnable "\nUnable to load playlist %s.\n"
+#define MSGTR_Exit_SIGILL_RTCpuSel \
+"- MPlayer crashed by an 'Illegal Instruction'.\n"\
+" It may be a bug in our new runtime CPU-detection code...\n"\
+" Please read DOCS/HTML/en/bugreports.html.\n"
+#define MSGTR_Exit_SIGILL \
+"- MPlayer crashed by an 'Illegal Instruction'.\n"\
+" It usually happens when you run it on a CPU different than the one it was\n"\
+" compiled/optimized for.\n"\
+" Verify this!\n"
+#define MSGTR_Exit_SIGSEGV_SIGFPE \
+"- MPlayer crashed by bad usage of CPU/FPU/RAM.\n"\
+" Recompile MPlayer with --enable-debug and make a 'gdb' backtrace and\n"\
+" disassembly. Details in DOCS/HTML/en/bugreports_what.html#bugreports_crash.\n"
+#define MSGTR_Exit_SIGCRASH \
+"- MPlayer crashed. This shouldn't happen.\n"\
+" It can be a bug in the MPlayer code _or_ in your drivers _or_ in your\n"\
+" gcc version. If you think it's MPlayer's fault, please read\n"\
+" DOCS/HTML/en/bugreports.html and follow the instructions there. We can't and\n"\
+" won't help unless you provide this information when reporting a possible bug.\n"
+#define MSGTR_LoadingConfig "Loading config '%s'\n"
+#define MSGTR_LoadingProtocolProfile "Loading protocol-related profile '%s'\n"
+#define MSGTR_LoadingExtensionProfile "Loading extension-related profile '%s'\n"
+#define MSGTR_AddedSubtitleFile "SUB: Added subtitle file (%d): %s\n"
+#define MSGTR_RemovedSubtitleFile "SUB: Removed subtitle file (%d): %s\n"
+#define MSGTR_ErrorOpeningOutputFile "Error opening file [%s] for writing!\n"
+#define MSGTR_CommandLine "CommandLine:"
+#define MSGTR_RTCDeviceNotOpenable "Failed to open %s: %s (it should be readable by the user.)\n"
+#define MSGTR_LinuxRTCInitErrorIrqpSet "Linux RTC init error in ioctl (rtc_irqp_set %lu): %s\n"
+#define MSGTR_IncreaseRTCMaxUserFreq "Try adding \"echo %lu > /proc/sys/dev/rtc/max-user-freq\" to your system startup scripts.\n"
+#define MSGTR_LinuxRTCInitErrorPieOn "Linux RTC init error in ioctl (rtc_pie_on): %s\n"
+#define MSGTR_UsingTimingType "Using %s timing.\n"
+#define MSGTR_NoIdleAndGui "The -idle option cannot be used with GMPlayer.\n"
+#define MSGTR_MenuInitialized "Menu initialized: %s\n"
+#define MSGTR_MenuInitFailed "Menu init failed.\n"
+#define MSGTR_Getch2InitializedTwice "WARNING: getch2_init called twice!\n"
+#define MSGTR_DumpstreamFdUnavailable "Cannot dump this stream - no file descriptor available.\n"
+#define MSGTR_CantOpenLibmenuFilterWithThisRootMenu "Can't open libmenu video filter with root menu %s.\n"
+#define MSGTR_AudioFilterChainPreinitError "Error at audio filter chain pre-init!\n"
+#define MSGTR_LinuxRTCReadError "Linux RTC read error: %s\n"
+#define MSGTR_SoftsleepUnderflow "Warning! Softsleep underflow!\n"
+#define MSGTR_DvdnavNullEvent "DVDNAV Event NULL?!\n"
+#define MSGTR_DvdnavHighlightEventBroken "DVDNAV Event: Highlight event broken\n"
+#define MSGTR_DvdnavEvent "DVDNAV Event: %s\n"
+#define MSGTR_DvdnavHighlightHide "DVDNAV Event: Highlight Hide\n"
+#define MSGTR_DvdnavStillFrame "######################################## DVDNAV Event: Still Frame: %d sec(s)\n"
+#define MSGTR_DvdnavNavStop "DVDNAV Event: Nav Stop\n"
+#define MSGTR_DvdnavNavNOP "DVDNAV Event: Nav NOP\n"
+#define MSGTR_DvdnavNavSpuStreamChangeVerbose "DVDNAV Event: Nav SPU Stream Change: phys: %d/%d/%d logical: %d\n"
+#define MSGTR_DvdnavNavSpuStreamChange "DVDNAV Event: Nav SPU Stream Change: phys: %d logical: %d\n"
+#define MSGTR_DvdnavNavAudioStreamChange "DVDNAV Event: Nav Audio Stream Change: phys: %d logical: %d\n"
+#define MSGTR_DvdnavNavVTSChange "DVDNAV Event: Nav VTS Change\n"
+#define MSGTR_DvdnavNavCellChange "DVDNAV Event: Nav Cell Change\n"
+#define MSGTR_DvdnavNavSpuClutChange "DVDNAV Event: Nav SPU CLUT Change\n"
+#define MSGTR_DvdnavNavSeekDone "DVDNAV Event: Nav Seek Done\n"
+#define MSGTR_MenuCall "Menu call\n"
+#define MSGTR_MasterQuit "Option -udp-slave: exiting because master exited\n"
+#define MSGTR_InvalidIP "Option -udp-ip: invalid IP address\n"
+
+// --- edit decision lists
+#define MSGTR_EdlOutOfMem "Can't allocate enough memory to hold EDL data.\n"
+#define MSGTR_EdlOutOfMemFile "Can't allocate enough memory to hold EDL file name [%s].\n"
+#define MSGTR_EdlRecordsNo "Read %d EDL actions.\n"
+#define MSGTR_EdlQueueEmpty "There are no EDL actions to take care of.\n"
+#define MSGTR_EdlCantOpenForWrite "Can't open EDL file [%s] for writing.\n"
+#define MSGTR_EdlCantOpenForRead "Can't open EDL file [%s] for reading.\n"
+#define MSGTR_EdlNOsh_video "Cannot use EDL without video, disabling.\n"
+#define MSGTR_EdlNOValidLine "Invalid EDL line: %s\n"
+#define MSGTR_EdlBadlyFormattedLine "Badly formatted EDL line [%d], discarding.\n"
+#define MSGTR_EdlBadLineOverlap "Last stop position was [%f]; next start is [%f].\n"\
+"Entries must be in chronological order, cannot overlap. Discarding.\n"
+#define MSGTR_EdlBadLineBadStop "Stop time has to be after start time.\n"
+#define MSGTR_EdloutBadStop "EDL skip canceled, last start > stop\n"
+#define MSGTR_EdloutStartSkip "EDL skip start, press 'i' again to end block.\n"
+#define MSGTR_EdloutEndSkip "EDL skip end, line written.\n"
+#define MSGTR_MPEndposNoSizeBased "Option -endpos in MPlayer does not yet support size units.\n"
+
+// mplayer.c OSD
+#define MSGTR_OSDenabled "enabled"
+#define MSGTR_OSDdisabled "disabled"
+#define MSGTR_OSDAudio "Audio: %s"
+#define MSGTR_OSDVideo "Video: %s"
+#define MSGTR_OSDChannel "Channel: %s"
+#define MSGTR_OSDSubDelay "Sub delay: %d ms"
+#define MSGTR_OSDSpeed "Speed: x %6.2f"
+#define MSGTR_OSDosd "OSD: %s"
+#define MSGTR_OSDChapter "Chapter: (%d) %s"
+#define MSGTR_OSDAngle "Angle: %d/%d"
+#define MSGTR_OSDDeinterlace "Deinterlace: %s"
+
+// property values
+#define MSGTR_Enabled "enabled"
+#define MSGTR_EnabledEdl "enabled (EDL)"
+#define MSGTR_Disabled "disabled"
+#define MSGTR_HardFrameDrop "hard"
+#define MSGTR_Unknown "unknown"
+#define MSGTR_Bottom "bottom"
+#define MSGTR_Center "center"
+#define MSGTR_Top "top"
+#define MSGTR_SubSourceFile "file"
+#define MSGTR_SubSourceVobsub "vobsub"
+#define MSGTR_SubSourceDemux "embedded"
+
+// OSD bar names
+#define MSGTR_Volume "Volume"
+#define MSGTR_Panscan "Panscan"
+#define MSGTR_Gamma "Gamma"
+#define MSGTR_Brightness "Brightness"
+#define MSGTR_Contrast "Contrast"
+#define MSGTR_Saturation "Saturation"
+#define MSGTR_Hue "Hue"
+#define MSGTR_Balance "Balance"
+
+// property state
+#define MSGTR_LoopStatus "Loop: %s"
+#define MSGTR_MuteStatus "Mute: %s"
+#define MSGTR_AVDelayStatus "A-V delay: %s"
+#define MSGTR_OnTopStatus "Stay on top: %s"
+#define MSGTR_RootwinStatus "Rootwin: %s"
+#define MSGTR_BorderStatus "Border: %s"
+#define MSGTR_FramedroppingStatus "Framedropping: %s"
+#define MSGTR_VSyncStatus "VSync: %s"
+#define MSGTR_SubSelectStatus "Subtitles: %s"
+#define MSGTR_SubSourceStatus "Sub source: %s"
+#define MSGTR_SubPosStatus "Sub position: %s/100"
+#define MSGTR_SubAlignStatus "Sub alignment: %s"
+#define MSGTR_SubDelayStatus "Sub delay: %s"
+#define MSGTR_SubScale "Sub Scale: %s"
+#define MSGTR_SubVisibleStatus "Subtitles: %s"
+#define MSGTR_SubForcedOnlyStatus "Forced sub only: %s"
+
+// mencoder.c
+#define MSGTR_UsingPass3ControlFile "Using pass3 control file: %s\n"
+#define MSGTR_MissingFilename "\nFilename missing.\n\n"
+#define MSGTR_CannotOpenFile_Device "Cannot open file/device.\n"
+#define MSGTR_CannotOpenDemuxer "Cannot open demuxer.\n"
+#define MSGTR_NoAudioEncoderSelected "\nNo audio encoder (-oac) selected. Select one (see -oac help) or use -nosound.\n"
+#define MSGTR_NoVideoEncoderSelected "\nNo video encoder (-ovc) selected. Select one (see -ovc help).\n"
+#define MSGTR_CannotOpenOutputFile "Cannot open output file '%s'.\n"
+#define MSGTR_EncoderOpenFailed "Failed to open the encoder.\n"
+#define MSGTR_MencoderWrongFormatAVI "\nWARNING: OUTPUT FILE FORMAT IS _AVI_. See -of help.\n"
+#define MSGTR_MencoderWrongFormatMPG "\nWARNING: OUTPUT FILE FORMAT IS _MPEG_. See -of help.\n"
+#define MSGTR_MissingOutputFilename "No output file specified, please see the -o option."
+#define MSGTR_ForcingOutputFourcc "Forcing output FourCC to %x [%.4s].\n"
+#define MSGTR_ForcingOutputAudiofmtTag "Forcing output audio format tag to 0x%x.\n"
+#define MSGTR_DuplicateFrames "\n%d duplicate frame(s)!\n"
+#define MSGTR_SkipFrame "\nSkipping frame!\n"
+#define MSGTR_ResolutionDoesntMatch "\nNew video file has different resolution or colorspace than the previous one.\n"
+#define MSGTR_FrameCopyFileMismatch "\nAll video files must have identical fps, resolution, and codec for -ovc copy.\n"
+#define MSGTR_AudioCopyFileMismatch "\nAll files must have identical audio codec and format for -oac copy.\n"
+#define MSGTR_NoAudioFileMismatch "\nCannot mix video-only files with audio and video files. Try -nosound.\n"
+#define MSGTR_NoSpeedWithFrameCopy "WARNING: -speed is not guaranteed to work correctly with -oac copy!\n"\
+"Your encode might be broken!\n"
+#define MSGTR_ErrorWritingFile "%s: Error writing file.\n"
+#define MSGTR_FlushingVideoFrames "\nFlushing video frames.\n"
+#define MSGTR_FiltersHaveNotBeenConfiguredEmptyFile "Filters have not been configured! Empty file?\n"
+#define MSGTR_RecommendedVideoBitrate "Recommended video bitrate for %s CD: %d\n"
+#define MSGTR_VideoStreamResult "\nVideo stream: %8.3f kbit/s (%d B/s) size: %"PRIu64" bytes %5.3f secs %d frames\n"
+#define MSGTR_AudioStreamResult "\nAudio stream: %8.3f kbit/s (%d B/s) size: %"PRIu64" bytes %5.3f secs\n"
+#define MSGTR_EdlSkipStartEndCurrent "EDL SKIP: Start: %.2f End: %.2f Current: V: %.2f A: %.2f \r"
+#define MSGTR_OpenedStream "success: format: %d data: 0x%X - 0x%x\n"
+#define MSGTR_VCodecFramecopy "videocodec: framecopy (%dx%d %dbpp fourcc=%x)\n"
+#define MSGTR_ACodecFramecopy "audiocodec: framecopy (format=%x chans=%d rate=%d bits=%d B/s=%d sample-%d)\n"
+#define MSGTR_CBRPCMAudioSelected "CBR PCM audio selected.\n"
+#define MSGTR_MP3AudioSelected "MP3 audio selected.\n"
+#define MSGTR_CannotAllocateBytes "Couldn't allocate %d bytes.\n"
+#define MSGTR_SettingAudioDelay "Setting audio delay to %5.3fs.\n"
+#define MSGTR_SettingVideoDelay "Setting video delay to %5.3fs.\n"
+#define MSGTR_SettingAudioInputGain "Setting audio input gain to %f.\n"
+#define MSGTR_LamePresetEquals "\npreset=%s\n\n"
+#define MSGTR_LimitingAudioPreload "Limiting audio preload to 0.4s.\n"
+#define MSGTR_IncreasingAudioDensity "Increasing audio density to 4.\n"
+#define MSGTR_ZeroingAudioPreloadAndMaxPtsCorrection "Forcing audio preload to 0, max pts correction to 0.\n"
+#define MSGTR_CBRAudioByterate "\n\nCBR audio: %d bytes/sec, %d bytes/block\n"
+#define MSGTR_LameVersion "LAME version %s (%s)\n\n"
+#define MSGTR_InvalidBitrateForLamePreset "Error: The bitrate specified is out of the valid range for this preset.\n"\
+"\n"\
+"When using this mode you must enter a value between \"8\" and \"320\".\n"\
+"\n"\
+"For further information try: \"-lameopts preset=help\"\n"
+#define MSGTR_InvalidLamePresetOptions "Error: You did not enter a valid profile and/or options with preset.\n"\
+"\n"\
+"Available profiles are:\n"\
+"\n"\
+" <fast> standard\n"\
+" <fast> extreme\n"\
+" insane\n"\
+" <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"\
+" simply specify a bitrate. For example:\n"\
+" \"preset=185\" activates this\n"\
+" preset and uses 185 as an average kbps.\n"\
+"\n"\
+" Some examples:\n"\
+"\n"\
+" \"-lameopts fast:preset=standard \"\n"\
+" or \"-lameopts cbr:preset=192 \"\n"\
+" or \"-lameopts preset=172 \"\n"\
+" or \"-lameopts preset=extreme \"\n"\
+"\n"\
+"For further information try: \"-lameopts preset=help\"\n"
+#define MSGTR_LamePresetsLongInfo "\n"\
+"The preset switches are designed to provide the highest possible quality.\n"\
+"\n"\
+"They have for the most part been subjected to and tuned via rigorous double\n"\
+"blind listening tests to verify and achieve this objective.\n"\
+"\n"\
+"These are continually updated to coincide with the latest developments that\n"\
+"occur and as a result should provide you with nearly the best quality\n"\
+"currently possible from LAME.\n"\
+"\n"\
+"To activate these presets:\n"\
+"\n"\
+" For VBR modes (generally highest quality):\n"\
+"\n"\
+" \"preset=standard\" This preset should generally be transparent\n"\
+" to most people on most music and is already\n"\
+" quite high in quality.\n"\
+"\n"\
+" \"preset=extreme\" If you have extremely good hearing and similar\n"\
+" equipment, this preset will generally provide\n"\
+" slightly higher quality than the \"standard\"\n"\
+" mode.\n"\
+"\n"\
+" For CBR 320kbps (highest quality possible from the preset switches):\n"\
+"\n"\
+" \"preset=insane\" This preset will usually be overkill for most\n"\
+" people and most situations, but if you must\n"\
+" have the absolute highest quality with no\n"\
+" regard to filesize, this is the way to go.\n"\
+"\n"\
+" For ABR modes (high quality per given bitrate but not as high as VBR):\n"\
+"\n"\
+" \"preset=<kbps>\" Using this preset will usually give you good\n"\
+" quality at a specified bitrate. Depending on the\n"\
+" bitrate entered, this preset will determine the\n"\
+" optimal settings for that particular situation.\n"\
+" While this approach works, it is not nearly as\n"\
+" flexible as VBR, and usually will not attain the\n"\
+" same level of quality as VBR at higher bitrates.\n"\
+"\n"\
+"The following options are also available for the corresponding profiles:\n"\
+"\n"\
+" <fast> standard\n"\
+" <fast> extreme\n"\
+" insane\n"\
+" <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n"\
+" simply specify a bitrate. For example:\n"\
+" \"preset=185\" activates this\n"\
+" preset and uses 185 as an average kbps.\n"\
+"\n"\
+" \"fast\" - Enables the new fast VBR for a particular profile. The\n"\
+" disadvantage to the speed switch is that often times the\n"\
+" bitrate will be slightly higher than with the normal mode\n"\
+" and quality may be slightly lower also.\n"\
+" Warning: with the current version fast presets might result in too\n"\
+" high bitrate compared to regular presets.\n"\
+"\n"\
+" \"cbr\" - If you use the ABR mode (read above) with a significant\n"\
+" bitrate such as 80, 96, 112, 128, 160, 192, 224, 256, 320,\n"\
+" you can use the \"cbr\" option to force CBR mode encoding\n"\
+" instead of the standard abr mode. ABR does provide higher\n"\
+" quality but CBR may be useful in situations such as when\n"\
+" streaming an MP3 over the internet may be important.\n"\
+"\n"\
+" For example:\n"\
+"\n"\
+" \"-lameopts fast:preset=standard \"\n"\
+" or \"-lameopts cbr:preset=192 \"\n"\
+" or \"-lameopts preset=172 \"\n"\
+" or \"-lameopts preset=extreme \"\n"\
+"\n"\
+"\n"\
+"A few aliases are available for ABR mode:\n"\
+"phone => 16kbps/mono phon+/lw/mw-eu/sw => 24kbps/mono\n"\
+"mw-us => 40kbps/mono voice => 56kbps/mono\n"\
+"fm/radio/tape => 112kbps hifi => 160kbps\n"\
+"cd => 192kbps studio => 256kbps"
+#define MSGTR_LameCantInit \
+"Cannot set LAME options, check bitrate/samplerate, some very low bitrates\n"\
+"(<32) need lower samplerates (i.e. -srate 8000).\n"\
+"If everything else fails, try a preset."
+#define MSGTR_ConfigFileError "config file error"
+#define MSGTR_ErrorParsingCommandLine "error parsing command line"
+#define MSGTR_VideoStreamRequired "Video stream is mandatory!\n"
+#define MSGTR_ForcingInputFPS "Input fps will be interpreted as %5.3f instead.\n"
+#define MSGTR_RawvideoDoesNotSupportAudio "Output file format RAWVIDEO does not support audio - disabling audio.\n"
+#define MSGTR_DemuxerDoesntSupportNosound "This demuxer doesn't support -nosound yet.\n"
+#define MSGTR_MemAllocFailed "Memory allocation failed.\n"
+#define MSGTR_NoMatchingFilter "Couldn't find matching filter/ao format!\n"
+#define MSGTR_MP3WaveFormatSizeNot30 "sizeof(MPEGLAYER3WAVEFORMAT)==%d!=30, maybe broken C compiler?\n"
+#define MSGTR_NoLavcAudioCodecName "Audio LAVC, Missing codec name!\n"
+#define MSGTR_LavcAudioCodecNotFound "Audio LAVC, couldn't find encoder for codec %s.\n"
+#define MSGTR_CouldntAllocateLavcContext "Audio LAVC, couldn't allocate context!\n"
+#define MSGTR_CouldntOpenCodec "Couldn't open codec %s, br=%d.\n"
+#define MSGTR_CantCopyAudioFormat "Audio format 0x%x is incompatible with '-oac copy', please try '-oac pcm' instead or use '-fafmttag' to override it.\n"
+
+// cfg-mencoder.h
+#define MSGTR_MEncoderMP3LameHelp "\n\n"\
+" vbr=<0-4> variable bitrate method\n"\
+" 0: cbr (constant bitrate)\n"\
+" 1: mt (Mark Taylor VBR algorithm)\n"\
+" 2: rh (Robert Hegemann VBR algorithm - default)\n"\
+" 3: abr (average bitrate)\n"\
+" 4: mtrh (Mark Taylor Robert Hegemann VBR algorithm)\n"\
+"\n"\
+" abr average bitrate\n"\
+"\n"\
+" cbr constant bitrate\n"\
+" Also forces CBR mode encoding on subsequent ABR presets modes.\n"\
+"\n"\
+" br=<0-1024> specify bitrate in kBit (CBR and ABR only)\n"\
+"\n"\
+" q=<0-9> quality (0-highest, 9-lowest) (only for VBR)\n"\
+"\n"\
+" aq=<0-9> algorithmic quality (0-best/slowest, 9-worst/fastest)\n"\
+"\n"\
+" ratio=<1-100> compression ratio\n"\
+"\n"\
+" vol=<0-10> set audio input gain\n"\
+"\n"\
+" mode=<0-3> (default: auto)\n"\
+" 0: stereo\n"\
+" 1: joint-stereo\n"\
+" 2: dualchannel\n"\
+" 3: mono\n"\
+"\n"\
+" padding=<0-2>\n"\
+" 0: no\n"\
+" 1: all\n"\
+" 2: adjust\n"\
+"\n"\
+" fast Switch on faster encoding on subsequent VBR presets modes,\n"\
+" slightly lower quality and higher bitrates.\n"\
+"\n"\
+" preset=<value> Provide the highest possible quality settings.\n"\
+" medium: VBR encoding, good quality\n"\
+" (150-180 kbps bitrate range)\n"\
+" standard: VBR encoding, high quality\n"\
+" (170-210 kbps bitrate range)\n"\
+" extreme: VBR encoding, very high quality\n"\
+" (200-240 kbps bitrate range)\n"\
+" insane: CBR encoding, highest preset quality\n"\
+" (320 kbps bitrate)\n"\
+" <8-320>: ABR encoding at average given kbps bitrate.\n\n"
+
+// codec-cfg.c
+#define MSGTR_DuplicateFourcc "duplicated FourCC"
+#define MSGTR_TooManyFourccs "too many FourCCs/formats..."
+#define MSGTR_ParseError "parse error"
+#define MSGTR_ParseErrorFIDNotNumber "parse error (format ID not a number?)"
+#define MSGTR_ParseErrorFIDAliasNotNumber "parse error (format ID alias not a number?)"
+#define MSGTR_DuplicateFID "duplicated format ID"
+#define MSGTR_TooManyOut "too many out..."
+#define MSGTR_InvalidCodecName "\ncodec(%s) name is not valid!\n"
+#define MSGTR_CodecLacksFourcc "\ncodec(%s) does not have FourCC/format!\n"
+#define MSGTR_CodecLacksDriver "\ncodec(%s) does not have a driver!\n"
+#define MSGTR_CodecNeedsDLL "\ncodec(%s) needs a 'dll'!\n"
+#define MSGTR_CodecNeedsOutfmt "\ncodec(%s) needs an 'outfmt'!\n"
+#define MSGTR_CantAllocateComment "Can't allocate memory for comment. "
+#define MSGTR_GetTokenMaxNotLessThanMAX_NR_TOKEN "get_token(): max >= MAX_MR_TOKEN!"
+#define MSGTR_ReadingFile "Reading %s: "
+#define MSGTR_CantOpenFileError "Can't open '%s': %s\n"
+#define MSGTR_CantGetMemoryForLine "Can't get memory for 'line': %s\n"
+#define MSGTR_CantReallocCodecsp "Can't realloc '*codecsp': %s\n"
+#define MSGTR_CodecNameNotUnique "Codec name '%s' isn't unique."
+#define MSGTR_CantStrdupName "Can't strdup -> 'name': %s\n"
+#define MSGTR_CantStrdupInfo "Can't strdup -> 'info': %s\n"
+#define MSGTR_CantStrdupDriver "Can't strdup -> 'driver': %s\n"
+#define MSGTR_CantStrdupDLL "Can't strdup -> 'dll': %s"
+#define MSGTR_AudioVideoCodecTotals "%d audio & %d video codecs\n"
+#define MSGTR_CodecDefinitionIncorrect "Codec is not defined correctly."
+#define MSGTR_OutdatedCodecsConf "This codecs.conf is too old and incompatible with this MPlayer release!"
+
+// fifo.c
+#define MSGTR_CannotMakePipe "Cannot make PIPE!\n"
+
+// parser-mecmd.c, parser-mpcmd.c
+#define MSGTR_NoFileGivenOnCommandLine "'--' indicates no more options, but no filename was given on the command line.\n"
+#define MSGTR_TheLoopOptionMustBeAnInteger "The loop option must be an integer: %s\n"
+#define MSGTR_UnknownOptionOnCommandLine "Unknown option on the command line: -%s\n"
+#define MSGTR_ErrorParsingOptionOnCommandLine "Error parsing option on the command line: -%s\n"
+#define MSGTR_InvalidPlayEntry "Invalid play entry %s\n"
+#define MSGTR_NotAnMEncoderOption "-%s is not an MEncoder option\n"
+#define MSGTR_NoFileGiven "No file given\n"
+
+// m_config.c
+#define MSGTR_SaveSlotTooOld "Save slot found from lvl %d is too old: %d !!!\n"
+#define MSGTR_InvalidCfgfileOption "The %s option can't be used in a config file.\n"
+#define MSGTR_InvalidCmdlineOption "The %s option can't be used on the command line.\n"
+#define MSGTR_InvalidSuboption "Error: option '%s' has no suboption '%s'.\n"
+#define MSGTR_MissingSuboptionParameter "Error: suboption '%s' of '%s' must have a parameter!\n"
+#define MSGTR_MissingOptionParameter "Error: option '%s' must have a parameter!\n"
+#define MSGTR_OptionListHeader "\n Name Type Min Max Global CL Cfg\n\n"
+#define MSGTR_TotalOptions "\nTotal: %d options\n"
+#define MSGTR_ProfileInclusionTooDeep "WARNING: Profile inclusion too deep.\n"
+#define MSGTR_NoProfileDefined "No profiles have been defined.\n"
+#define MSGTR_AvailableProfiles "Available profiles:\n"
+#define MSGTR_UnknownProfile "Unknown profile '%s'.\n"
+#define MSGTR_Profile "Profile %s: %s\n"
+
+// m_property.c
+#define MSGTR_PropertyListHeader "\n Name Type Min Max\n\n"
+#define MSGTR_TotalProperties "\nTotal: %d properties\n"
+
+// loader/ldt_keeper.c
+#define MSGTR_LOADER_DYLD_Warning "WARNING: Attempting to use DLL codecs but environment variable\n DYLD_BIND_AT_LAUNCH not set. This will likely crash.\n"
+
+
+// ====================== GUI messages/buttons ========================
+
+// --- labels ---
+#define MSGTR_About "About"
+#define MSGTR_FileSelect "Select file..."
+#define MSGTR_SubtitleSelect "Select subtitle..."
+#define MSGTR_OtherSelect "Select..."
+#define MSGTR_AudioFileSelect "Select external audio channel..."
+#define MSGTR_FontSelect "Select font..."
+// Note: If you change MSGTR_PlayList please see if it still fits MSGTR_MENU_PlayList
+#define MSGTR_PlayList "Playlist"
+#define MSGTR_Equalizer "Equalizer"
+#define MSGTR_ConfigureEqualizer "Configure Equalizer"
+#define MSGTR_SkinBrowser "Skin Browser"
+#define MSGTR_Network "Network streaming..."
+// Note: If you change MSGTR_Preferences please see if it still fits MSGTR_MENU_Preferences
+#define MSGTR_Preferences "Preferences"
+#define MSGTR_AudioPreferences "Audio driver configuration"
+#define MSGTR_NoMediaOpened "No media opened."
+#define MSGTR_VCDTrack "VCD track %d"
+#define MSGTR_NoChapter "No chapter"
+#define MSGTR_Chapter "Chapter %d"
+#define MSGTR_NoFileLoaded "No file loaded."
+
+// --- buttons ---
+#define MSGTR_Ok "OK"
+#define MSGTR_Cancel "Cancel"
+#define MSGTR_Add "Add"
+#define MSGTR_Remove "Remove"
+#define MSGTR_Clear "Clear"
+#define MSGTR_Config "Config"
+#define MSGTR_ConfigDriver "Configure driver"
+#define MSGTR_Browse "Browse"
+
+// --- error messages ---
+#define MSGTR_NEMDB "Sorry, not enough memory to draw buffer."
+#define MSGTR_NEMFMR "Sorry, not enough memory for menu rendering."
+#define MSGTR_IDFGCVD "Sorry, I did not find a GUI-compatible video output driver."
+#define MSGTR_NEEDLAVC "Sorry, you cannot play non-MPEG files with your DXR3/H+ device without reencoding.\nPlease enable lavc in the DXR3/H+ configuration box."
+#define MSGTR_UNKNOWNWINDOWTYPE "Unknown window type found ..."
+
+// --- skin loader error messages
+#define MSGTR_SKIN_ERRORMESSAGE "[skin] error in skin config file on line %d: %s"
+#define MSGTR_SKIN_WARNING1 "[skin] warning: in config file line %d:\nwidget (%s) found but no \"section\" found before"
+#define MSGTR_SKIN_WARNING2 "[skin] warning: in config file line %d:\nwidget (%s) found but no \"subsection\" found before"
+#define MSGTR_SKIN_WARNING3 "[skin] warning: in config file line %d:\nthis subsection is not supported by widget (%s)"
+#define MSGTR_SKIN_SkinFileNotFound "[skin] file ( %s ) not found.\n"
+#define MSGTR_SKIN_SkinFileNotReadable "[skin] file ( %s ) not readable.\n"
+#define MSGTR_SKIN_BITMAP_16bit "Bitmaps of 16 bits or less depth not supported (%s).\n"
+#define MSGTR_SKIN_BITMAP_FileNotFound "File not found (%s)\n"
+#define MSGTR_SKIN_BITMAP_BMPReadError "BMP read error (%s)\n"
+#define MSGTR_SKIN_BITMAP_TGAReadError "TGA read error (%s)\n"
+#define MSGTR_SKIN_BITMAP_PNGReadError "PNG read error (%s)\n"
+#define MSGTR_SKIN_BITMAP_RLENotSupported "RLE packed TGA not supported (%s)\n"
+#define MSGTR_SKIN_BITMAP_UnknownFileType "unknown file type (%s)\n"
+#define MSGTR_SKIN_BITMAP_ConversionError "24 bit to 32 bit conversion error (%s)\n"
+#define MSGTR_SKIN_BITMAP_UnknownMessage "unknown message: %s\n"
+#define MSGTR_SKIN_FONT_NotEnoughtMemory "not enough memory\n"
+#define MSGTR_SKIN_FONT_TooManyFontsDeclared "Too many fonts declared.\n"
+#define MSGTR_SKIN_FONT_FontFileNotFound "Font file not found.\n"
+#define MSGTR_SKIN_FONT_FontImageNotFound "Font image file not found.\n"
+#define MSGTR_SKIN_FONT_NonExistentFontID "non-existent font identifier (%s)\n"
+#define MSGTR_SKIN_UnknownParameter "unknown parameter (%s)\n"
+#define MSGTR_SKIN_SKINCFG_SkinNotFound "Skin not found (%s).\n"
+#define MSGTR_SKIN_SKINCFG_SelectedSkinNotFound "Selected skin ( %s ) not found, trying 'default'...\n"
+#define MSGTR_SKIN_SKINCFG_SkinCfgReadError "skin config file read error (%s)\n"
+#define MSGTR_SKIN_LABEL "Skins:"
+
+// --- GTK menus
+#define MSGTR_MENU_AboutMPlayer "About MPlayer"
+#define MSGTR_MENU_Open "Open..."
+#define MSGTR_MENU_PlayFile "Play file..."
+#define MSGTR_MENU_PlayVCD "Play VCD..."
+#define MSGTR_MENU_PlayDVD "Play DVD..."
+#define MSGTR_MENU_PlayURL "Play URL..."
+#define MSGTR_MENU_LoadSubtitle "Load subtitle..."
+#define MSGTR_MENU_DropSubtitle "Drop subtitle..."
+#define MSGTR_MENU_LoadExternAudioFile "Load external audio file..."
+#define MSGTR_MENU_Playing "Playing"
+#define MSGTR_MENU_Play "Play"
+#define MSGTR_MENU_Pause "Pause"
+#define MSGTR_MENU_Stop "Stop"
+#define MSGTR_MENU_NextStream "Next stream"
+#define MSGTR_MENU_PrevStream "Prev stream"
+#define MSGTR_MENU_Size "Size"
+#define MSGTR_MENU_HalfSize "Half size"
+#define MSGTR_MENU_NormalSize "Normal size"
+#define MSGTR_MENU_DoubleSize "Double size"
+#define MSGTR_MENU_FullScreen "Fullscreen"
+#define MSGTR_MENU_DVD "DVD"
+#define MSGTR_MENU_VCD "VCD"
+#define MSGTR_MENU_PlayDisc "Open disc..."
+#define MSGTR_MENU_ShowDVDMenu "Show DVD menu"
+#define MSGTR_MENU_Titles "Titles"
+#define MSGTR_MENU_Title "Title %2d"
+#define MSGTR_MENU_None "(none)"
+#define MSGTR_MENU_Chapters "Chapters"
+#define MSGTR_MENU_Chapter "Chapter %2d"
+#define MSGTR_MENU_AudioLanguages "Audio languages"
+#define MSGTR_MENU_SubtitleLanguages "Subtitle languages"
+#define MSGTR_MENU_PlayList MSGTR_PlayList
+#define MSGTR_MENU_SkinBrowser "Skin browser"
+#define MSGTR_MENU_Preferences MSGTR_Preferences
+#define MSGTR_MENU_Exit "Exit..."
+#define MSGTR_MENU_Mute "Mute"
+#define MSGTR_MENU_Original "Original"
+#define MSGTR_MENU_AspectRatio "Aspect ratio"
+#define MSGTR_MENU_AudioTrack "Audio track"
+#define MSGTR_MENU_Track "Track %d"
+#define MSGTR_MENU_VideoTrack "Video track"
+#define MSGTR_MENU_Subtitles "Subtitles"
+
+// --- equalizer
+// Note: If you change MSGTR_EQU_Audio please see if it still fits MSGTR_PREFERENCES_Audio
+#define MSGTR_EQU_Audio "Audio"
+// Note: If you change MSGTR_EQU_Video please see if it still fits MSGTR_PREFERENCES_Video
+#define MSGTR_EQU_Video "Video"
+#define MSGTR_EQU_Contrast "Contrast: "
+#define MSGTR_EQU_Brightness "Brightness: "
+#define MSGTR_EQU_Hue "Hue: "
+#define MSGTR_EQU_Saturation "Saturation: "
+#define MSGTR_EQU_Front_Left "Front Left"
+#define MSGTR_EQU_Front_Right "Front Right"
+#define MSGTR_EQU_Back_Left "Rear Left"
+#define MSGTR_EQU_Back_Right "Rear Right"
+#define MSGTR_EQU_Center "Center"
+#define MSGTR_EQU_Bass "Bass"
+#define MSGTR_EQU_All "All"
+#define MSGTR_EQU_Channel1 "Channel 1:"
+#define MSGTR_EQU_Channel2 "Channel 2:"
+#define MSGTR_EQU_Channel3 "Channel 3:"
+#define MSGTR_EQU_Channel4 "Channel 4:"
+#define MSGTR_EQU_Channel5 "Channel 5:"
+#define MSGTR_EQU_Channel6 "Channel 6:"
+
+// --- playlist
+#define MSGTR_PLAYLIST_Path "Path"
+#define MSGTR_PLAYLIST_Selected "Selected files"
+#define MSGTR_PLAYLIST_Files "Files"
+#define MSGTR_PLAYLIST_DirectoryTree "Directory tree"
+
+// --- preferences
+#define MSGTR_PREFERENCES_Audio MSGTR_EQU_Audio
+#define MSGTR_PREFERENCES_Video MSGTR_EQU_Video
+#define MSGTR_PREFERENCES_SubtitleOSD "Subtitles & OSD"
+#define MSGTR_PREFERENCES_Codecs "Codecs & demuxer"
+// Note: If you change MSGTR_PREFERENCES_Misc see if it still fits MSGTR_PREFERENCES_FRAME_Misc
+#define MSGTR_PREFERENCES_Misc "Misc"
+#define MSGTR_PREFERENCES_None "None"
+#define MSGTR_PREFERENCES_DriverDefault "driver default"
+#define MSGTR_PREFERENCES_AvailableDrivers "Available drivers:"
+#define MSGTR_PREFERENCES_DoNotPlaySound "Do not play sound"
+#define MSGTR_PREFERENCES_NormalizeSound "Normalize sound"
+#define MSGTR_PREFERENCES_EnableEqualizer "Enable equalizer"
+#define MSGTR_PREFERENCES_SoftwareMixer "Enable Software Mixer"
+#define MSGTR_PREFERENCES_ExtraStereo "Enable extra stereo"
+#define MSGTR_PREFERENCES_Coefficient "Coefficient:"
+#define MSGTR_PREFERENCES_AudioDelay "Audio delay"
+#define MSGTR_PREFERENCES_DoubleBuffer "Enable double buffering"
+#define MSGTR_PREFERENCES_DirectRender "Enable direct rendering"
+#define MSGTR_PREFERENCES_FrameDrop "Enable frame dropping"
+#define MSGTR_PREFERENCES_HFrameDrop "Enable HARD frame dropping (dangerous)"
+#define MSGTR_PREFERENCES_Flip "Flip image upside down"
+#define MSGTR_PREFERENCES_Panscan "Panscan: "
+#define MSGTR_PREFERENCES_OSDTimer "Timer and indicators"
+#define MSGTR_PREFERENCES_OSDProgress "Progressbars only"
+#define MSGTR_PREFERENCES_OSDTimerPercentageTotalTime "Timer, percentage and total time"
+#define MSGTR_PREFERENCES_Subtitle "Subtitle:"
+#define MSGTR_PREFERENCES_SUB_Delay "Delay: "
+#define MSGTR_PREFERENCES_SUB_FPS "FPS:"
+#define MSGTR_PREFERENCES_SUB_POS "Position: "
+#define MSGTR_PREFERENCES_SUB_AutoLoad "Disable subtitle autoloading"
+#define MSGTR_PREFERENCES_SUB_Unicode "Unicode subtitle"
+#define MSGTR_PREFERENCES_SUB_MPSUB "Convert the given subtitle to MPlayer's subtitle format"
+#define MSGTR_PREFERENCES_SUB_SRT "Convert the given subtitle to the time based SubViewer (SRT) format"
+#define MSGTR_PREFERENCES_SUB_Overlap "Toggle subtitle overlapping"
+#define MSGTR_PREFERENCES_SUB_USE_ASS "SSA/ASS subtitle rendering"
+#define MSGTR_PREFERENCES_SUB_ASS_USE_MARGINS "Use margins"
+#define MSGTR_PREFERENCES_SUB_ASS_TOP_MARGIN "Top: "
+#define MSGTR_PREFERENCES_SUB_ASS_BOTTOM_MARGIN "Bottom: "
+#define MSGTR_PREFERENCES_Font "Font:"
+#define MSGTR_PREFERENCES_FontFactor "Font factor:"
+#define MSGTR_PREFERENCES_PostProcess "Enable postprocessing"
+#define MSGTR_PREFERENCES_AutoQuality "Auto quality: "
+#define MSGTR_PREFERENCES_NI "Use non-interleaved AVI parser"
+#define MSGTR_PREFERENCES_IDX "Rebuild index table, if needed"
+#define MSGTR_PREFERENCES_VideoCodecFamily "Video codec family:"
+#define MSGTR_PREFERENCES_AudioCodecFamily "Audio codec family:"
+#define MSGTR_PREFERENCES_FRAME_OSD_Level "OSD level"
+#define MSGTR_PREFERENCES_FRAME_Subtitle "Subtitle"
+#define MSGTR_PREFERENCES_FRAME_Font "Font"
+#define MSGTR_PREFERENCES_FRAME_PostProcess "Postprocessing"
+#define MSGTR_PREFERENCES_FRAME_CodecDemuxer "Codec & demuxer"
+#define MSGTR_PREFERENCES_FRAME_Cache "Cache"
+#define MSGTR_PREFERENCES_FRAME_Misc MSGTR_PREFERENCES_Misc
+#define MSGTR_PREFERENCES_Audio_Device "Device:"
+#define MSGTR_PREFERENCES_Audio_Mixer "Mixer:"
+#define MSGTR_PREFERENCES_Audio_MixerChannel "Mixer channel:"
+#define MSGTR_PREFERENCES_Message "Please remember that you need to restart playback for some options to take effect!"
+#define MSGTR_PREFERENCES_DXR3_VENC "Video encoder:"
+#define MSGTR_PREFERENCES_DXR3_LAVC "Use LAVC (FFmpeg)"
+#define MSGTR_PREFERENCES_FontEncoding1 "Unicode"
+#define MSGTR_PREFERENCES_FontEncoding2 "Western European Languages (ISO-8859-1)"
+#define MSGTR_PREFERENCES_FontEncoding3 "Western European Languages with Euro (ISO-8859-15)"
+#define MSGTR_PREFERENCES_FontEncoding4 "Slavic/Central European Languages (ISO-8859-2)"
+#define MSGTR_PREFERENCES_FontEncoding5 "Esperanto, Galician, Maltese, Turkish (ISO-8859-3)"
+#define MSGTR_PREFERENCES_FontEncoding6 "Old Baltic charset (ISO-8859-4)"
+#define MSGTR_PREFERENCES_FontEncoding7 "Cyrillic (ISO-8859-5)"
+#define MSGTR_PREFERENCES_FontEncoding8 "Arabic (ISO-8859-6)"
+#define MSGTR_PREFERENCES_FontEncoding9 "Modern Greek (ISO-8859-7)"
+#define MSGTR_PREFERENCES_FontEncoding10 "Turkish (ISO-8859-9)"
+#define MSGTR_PREFERENCES_FontEncoding11 "Baltic (ISO-8859-13)"
+#define MSGTR_PREFERENCES_FontEncoding12 "Celtic (ISO-8859-14)"
+#define MSGTR_PREFERENCES_FontEncoding13 "Hebrew charsets (ISO-8859-8)"
+#define MSGTR_PREFERENCES_FontEncoding14 "Russian (KOI8-R)"
+#define MSGTR_PREFERENCES_FontEncoding15 "Ukrainian, Belarusian (KOI8-U/RU)"
+#define MSGTR_PREFERENCES_FontEncoding16 "Simplified Chinese charset (CP936)"
+#define MSGTR_PREFERENCES_FontEncoding17 "Traditional Chinese charset (BIG5)"
+#define MSGTR_PREFERENCES_FontEncoding18 "Japanese charsets (SHIFT-JIS)"
+#define MSGTR_PREFERENCES_FontEncoding19 "Korean charset (CP949)"
+#define MSGTR_PREFERENCES_FontEncoding20 "Thai charset (CP874)"
+#define MSGTR_PREFERENCES_FontEncoding21 "Cyrillic Windows (CP1251)"
+#define MSGTR_PREFERENCES_FontEncoding22 "Slavic/Central European Windows (CP1250)"
+#define MSGTR_PREFERENCES_FontEncoding23 "Arabic Windows (CP1256)"
+#define MSGTR_PREFERENCES_FontNoAutoScale "No autoscale"
+#define MSGTR_PREFERENCES_FontPropWidth "Proportional to movie width"
+#define MSGTR_PREFERENCES_FontPropHeight "Proportional to movie height"
+#define MSGTR_PREFERENCES_FontPropDiagonal "Proportional to movie diagonal"
+#define MSGTR_PREFERENCES_FontEncoding "Encoding:"
+#define MSGTR_PREFERENCES_FontBlur "Blur:"
+#define MSGTR_PREFERENCES_FontOutLine "Outline:"
+#define MSGTR_PREFERENCES_FontTextScale "Text scale:"
+#define MSGTR_PREFERENCES_FontOSDScale "OSD scale:"
+#define MSGTR_PREFERENCES_Cache "Cache on/off"
+#define MSGTR_PREFERENCES_CacheSize "Cache size: "
+#define MSGTR_PREFERENCES_LoadFullscreen "Start in fullscreen"
+#define MSGTR_PREFERENCES_SaveWinPos "Save window position"
+#define MSGTR_PREFERENCES_XSCREENSAVER "Stop XScreenSaver"
+#define MSGTR_PREFERENCES_PlayBar "Enable playbar"
+#define MSGTR_PREFERENCES_AutoSync "AutoSync on/off"
+#define MSGTR_PREFERENCES_AutoSyncValue "Autosync: "
+#define MSGTR_PREFERENCES_CDROMDevice "CD-ROM device:"
+#define MSGTR_PREFERENCES_DVDDevice "DVD device:"
+#define MSGTR_PREFERENCES_FPS "Movie FPS:"
+#define MSGTR_PREFERENCES_ShowVideoWindow "Show video window when inactive"
+#define MSGTR_PREFERENCES_ArtsBroken "Newer aRts versions are incompatible "\
+ "with GTK 1.x and will crash GMPlayer!"
+
+// -- aboutbox
+#define MSGTR_ABOUT_UHU "GUI development sponsored by UHU Linux\n"
+#define MSGTR_ABOUT_Contributors "Code and documentation contributors\n"
+#define MSGTR_ABOUT_Codecs_libs_contributions "Codecs and third party libraries\n"
+#define MSGTR_ABOUT_Translations "Translations\n"
+#define MSGTR_ABOUT_Skins "Skins\n"
+
+// --- messagebox
+#define MSGTR_MSGBOX_LABEL_FatalError "Fatal error!"
+#define MSGTR_MSGBOX_LABEL_Error "Error!"
+#define MSGTR_MSGBOX_LABEL_Warning "Warning!"
+
+// bitmap.c
+#define MSGTR_NotEnoughMemoryC32To1 "[c32to1] not enough memory for image\n"
+#define MSGTR_NotEnoughMemoryC1To32 "[c1to32] not enough memory for image\n"
+
+// cfg.c
+#define MSGTR_ConfigFileReadError "[cfg] config file read error ...\n"
+#define MSGTR_UnableToSaveOption "[cfg] Unable to save the '%s' option.\n"
+
+// interface.c
+#define MSGTR_DeletingSubtitles "[GUI] Deleting subtitles.\n"
+#define MSGTR_LoadingSubtitles "[GUI] Loading subtitles: %s\n"
+#define MSGTR_AddingVideoFilter "[GUI] Adding video filter: %s\n"
+#define MSGTR_RemovingVideoFilter "[GUI] Removing video filter: %s\n"
+
+// mw.c
+#define MSGTR_NotAFile "This does not seem to be a file: %s !\n"
+
+// ws.c
+#define MSGTR_WS_CouldNotOpenDisplay "[ws] Could not open the display.\n"
+#define MSGTR_WS_RemoteDisplay "[ws] Remote display, disabling XMITSHM.\n"
+#define MSGTR_WS_NoXshm "[ws] Sorry, your system does not support the X shared memory extension.\n"
+#define MSGTR_WS_NoXshape "[ws] Sorry, your system does not support the XShape extension.\n"
+#define MSGTR_WS_ColorDepthTooLow "[ws] Sorry, the color depth is too low.\n"
+#define MSGTR_WS_TooManyOpenWindows "[ws] There are too many open windows.\n"
+#define MSGTR_WS_ShmError "[ws] shared memory extension error\n"
+#define MSGTR_WS_NotEnoughMemoryDrawBuffer "[ws] Sorry, not enough memory to draw buffer.\n"
+#define MSGTR_WS_DpmsUnavailable "DPMS not available?\n"
+#define MSGTR_WS_DpmsNotEnabled "Could not enable DPMS.\n"
+
+// wsxdnd.c
+#define MSGTR_WS_NotAFile "This does not seem to be a file...\n"
+#define MSGTR_WS_DDNothing "D&D: Nothing returned!\n"
+
+// ======================= video output drivers ========================
+
+#define MSGTR_VOincompCodec "The selected video_out device is incompatible with this codec.\n"\
+ "Try appending the scale filter to your filter list,\n"\
+ "e.g. -vf spp,scale instead of -vf spp.\n"
+#define MSGTR_VO_GenericError "This error has occurred"
+#define MSGTR_VO_UnableToAccess "Unable to access"
+#define MSGTR_VO_ExistsButNoDirectory "already exists, but is not a directory."
+#define MSGTR_VO_DirExistsButNotWritable "Output directory already exists, but is not writable."
+#define MSGTR_VO_DirExistsAndIsWritable "Output directory already exists and is writable."
+#define MSGTR_VO_CantCreateDirectory "Unable to create output directory."
+#define MSGTR_VO_CantCreateFile "Unable to create output file."
+#define MSGTR_VO_DirectoryCreateSuccess "Output directory successfully created."
+#define MSGTR_VO_ValueOutOfRange "value out of range"
+#define MSGTR_VO_NoValueSpecified "No value specified."
+#define MSGTR_VO_UnknownSuboptions "unknown suboption(s)"
+
+// aspect.c
+#define MSGTR_LIBVO_ASPECT_NoSuitableNewResFound "[ASPECT] Warning: No suitable new res found!\n"
+#define MSGTR_LIBVO_ASPECT_NoNewSizeFoundThatFitsIntoRes "[ASPECT] Error: No new size found that fits into res!\n"
+
+// font_load_ft.c
+#define MSGTR_LIBVO_FONT_LOAD_FT_NewFaceFailed "New_Face failed. Maybe the font path is wrong.\nPlease supply the text font file (~/.mplayer/subfont.ttf).\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_NewMemoryFaceFailed "New_Memory_Face failed..\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_SubFaceFailed "subtitle font: load_sub_face failed.\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_SubFontCharsetFailed "subtitle font: prepare_charset failed.\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_CannotPrepareSubtitleFont "Cannot prepare subtitle font.\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_CannotPrepareOSDFont "Cannot prepare OSD font.\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_CannotGenerateTables "Cannot generate tables.\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_DoneFreeTypeFailed "FT_Done_FreeType failed.\n"
+#define MSGTR_LIBVO_FONT_LOAD_FT_FontconfigNoMatch "Fontconfig failed to select a font. Trying without fontconfig...\n"
+
+// sub.c
+#define MSGTR_VO_SUB_Seekbar "Seekbar"
+#define MSGTR_VO_SUB_Play "Play"
+#define MSGTR_VO_SUB_Pause "Pause"
+#define MSGTR_VO_SUB_Stop "Stop"
+#define MSGTR_VO_SUB_Rewind "Rewind"
+#define MSGTR_VO_SUB_Forward "Forward"
+#define MSGTR_VO_SUB_Clock "Clock"
+#define MSGTR_VO_SUB_Contrast "Contrast"
+#define MSGTR_VO_SUB_Saturation "Saturation"
+#define MSGTR_VO_SUB_Volume "Volume"
+#define MSGTR_VO_SUB_Brightness "Brightness"
+#define MSGTR_VO_SUB_Hue "Hue"
+#define MSGTR_VO_SUB_Balance "Balance"
+
+// vo_3dfx.c
+#define MSGTR_LIBVO_3DFX_Only16BppSupported "[VO_3DFX] Only 16bpp supported!"
+#define MSGTR_LIBVO_3DFX_VisualIdIs "[VO_3DFX] Visual ID is %lx.\n"
+#define MSGTR_LIBVO_3DFX_UnableToOpenDevice "[VO_3DFX] Unable to open /dev/3dfx.\n"
+#define MSGTR_LIBVO_3DFX_Error "[VO_3DFX] Error: %d.\n"
+#define MSGTR_LIBVO_3DFX_CouldntMapMemoryArea "[VO_3DFX] Couldn't map 3dfx memory areas: %p,%p,%d.\n"
+#define MSGTR_LIBVO_3DFX_DisplayInitialized "[VO_3DFX] Initialized: %p.\n"
+#define MSGTR_LIBVO_3DFX_UnknownSubdevice "[VO_3DFX] Unknown subdevice: %s.\n"
+
+// vo_aa.c
+#define MSGTR_VO_AA_HelpHeader "\n\nHere are the aalib vo_aa suboptions:\n"
+#define MSGTR_VO_AA_AdditionalOptions "Additional options vo_aa provides:\n" \
+" help print this help message\n" \
+" osdcolor set OSD color\n subcolor set subtitle color\n" \
+" the color parameters are:\n 0 : normal\n" \
+" 1 : dim\n 2 : bold\n 3 : boldfont\n" \
+" 4 : reverse\n 5 : special\n\n\n"
+
+// vo_dxr3.c
+#define MSGTR_LIBVO_DXR3_UnableToLoadNewSPUPalette "[VO_DXR3] Unable to load new SPU palette!\n"
+#define MSGTR_LIBVO_DXR3_UnableToSetPlaymode "[VO_DXR3] Unable to set playmode!\n"
+#define MSGTR_LIBVO_DXR3_UnableToSetSubpictureMode "[VO_DXR3] Unable to set subpicture mode!\n"
+#define MSGTR_LIBVO_DXR3_UnableToGetTVNorm "[VO_DXR3] Unable to get TV norm!\n"
+#define MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate "[VO_DXR3] Auto-selected TV norm by framerate: "
+#define MSGTR_LIBVO_DXR3_UnableToSetTVNorm "[VO_DXR3] Unable to set TV norm!\n"
+#define MSGTR_LIBVO_DXR3_SettingUpForNTSC "[VO_DXR3] Setting up for NTSC.\n"
+#define MSGTR_LIBVO_DXR3_SettingUpForPALSECAM "[VO_DXR3] Setting up for PAL/SECAM.\n"
+#define MSGTR_LIBVO_DXR3_SettingAspectRatioTo43 "[VO_DXR3] Setting aspect ratio to 4:3.\n"
+#define MSGTR_LIBVO_DXR3_SettingAspectRatioTo169 "[VO_DXR3] Setting aspect ratio to 16:9.\n"
+#define MSGTR_LIBVO_DXR3_OutOfMemory "[VO_DXR3] out of memory\n"
+#define MSGTR_LIBVO_DXR3_UnableToAllocateKeycolor "[VO_DXR3] Unable to allocate keycolor!\n"
+#define MSGTR_LIBVO_DXR3_UnableToAllocateExactKeycolor "[VO_DXR3] Unable to allocate exact keycolor, using closest match (0x%lx).\n"
+#define MSGTR_LIBVO_DXR3_Uninitializing "[VO_DXR3] Uninitializing.\n"
+#define MSGTR_LIBVO_DXR3_FailedRestoringTVNorm "[VO_DXR3] Failed restoring TV norm!\n"
+#define MSGTR_LIBVO_DXR3_EnablingPrebuffering "[VO_DXR3] Enabling prebuffering.\n"
+#define MSGTR_LIBVO_DXR3_UsingNewSyncEngine "[VO_DXR3] Using new sync engine.\n"
+#define MSGTR_LIBVO_DXR3_UsingOverlay "[VO_DXR3] Using overlay.\n"
+#define MSGTR_LIBVO_DXR3_ErrorYouNeedToCompileMplayerWithX11 "[VO_DXR3] Error: Overlay requires compiling with X11 libs/headers installed.\n"
+#define MSGTR_LIBVO_DXR3_WillSetTVNormTo "[VO_DXR3] Will set TV norm to: "
+#define MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALPAL60 "auto-adjust to movie framerate (PAL/PAL-60)"
+#define MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALNTSC "auto-adjust to movie framerate (PAL/NTSC)"
+#define MSGTR_LIBVO_DXR3_UseCurrentNorm "Use current norm."
+#define MSGTR_LIBVO_DXR3_UseUnknownNormSuppliedCurrentNorm "Unknown norm supplied. Use current norm."
+#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTrying "[VO_DXR3] Error opening %s for writing, trying /dev/em8300 instead.\n"
+#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingMV "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_mv instead.\n"
+#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWell "[VO_DXR3] Error opening /dev/em8300 for writing as well!\nBailing out.\n"
+#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellMV "[VO_DXR3] Error opening /dev/em8300_mv for writing as well!\nBailing out.\n"
+#define MSGTR_LIBVO_DXR3_Opened "[VO_DXR3] Opened: %s.\n"
+#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingSP "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_sp instead.\n"
+#define MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellSP "[VO_DXR3] Error opening /dev/em8300_sp for writing as well!\nBailing out.\n"
+#define MSGTR_LIBVO_DXR3_UnableToOpenDisplayDuringHackSetup "[VO_DXR3] Unable to open display during overlay hack setup!\n"
+#define MSGTR_LIBVO_DXR3_UnableToInitX11 "[VO_DXR3] Unable to init X11!\n"
+#define MSGTR_LIBVO_DXR3_FailedSettingOverlayAttribute "[VO_DXR3] Failed setting overlay attribute.\n"
+#define MSGTR_LIBVO_DXR3_FailedSettingOverlayScreen "[VO_DXR3] Failed setting overlay screen!\nExiting.\n"
+#define MSGTR_LIBVO_DXR3_FailedEnablingOverlay "[VO_DXR3] Failed enabling overlay!\nExiting.\n"
+#define MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow "[VO_DXR3] Failed resizing overlay window!\n"
+#define MSGTR_LIBVO_DXR3_FailedSettingOverlayBcs "[VO_DXR3] Failed setting overlay bcs!\n"
+#define MSGTR_LIBVO_DXR3_FailedGettingOverlayYOffsetValues "[VO_DXR3] Failed getting overlay Y-offset values!\nExiting.\n"
+#define MSGTR_LIBVO_DXR3_FailedGettingOverlayXOffsetValues "[VO_DXR3] Failed getting overlay X-offset values!\nExiting.\n"
+#define MSGTR_LIBVO_DXR3_FailedGettingOverlayXScaleCorrection "[VO_DXR3] Failed getting overlay X scale correction!\nExiting.\n"
+#define MSGTR_LIBVO_DXR3_YOffset "[VO_DXR3] Yoffset: %d.\n"
+#define MSGTR_LIBVO_DXR3_XOffset "[VO_DXR3] Xoffset: %d.\n"
+#define MSGTR_LIBVO_DXR3_XCorrection "[VO_DXR3] Xcorrection: %d.\n"
+#define MSGTR_LIBVO_DXR3_FailedSetSignalMix "[VO_DXR3] Failed to set signal mix!\n"
+
+// vo_jpeg.c
+#define MSGTR_VO_JPEG_ProgressiveJPEG "Progressive JPEG enabled."
+#define MSGTR_VO_JPEG_NoProgressiveJPEG "Progressive JPEG disabled."
+#define MSGTR_VO_JPEG_BaselineJPEG "Baseline JPEG enabled."
+#define MSGTR_VO_JPEG_NoBaselineJPEG "Baseline JPEG disabled."
+
+// vo_mga.c
+#define MSGTR_LIBVO_MGA_AspectResized "[VO_MGA] aspect(): resized to %dx%d.\n"
+#define MSGTR_LIBVO_MGA_Uninit "[VO] uninit!\n"
+
+// mga_template.c
+#define MSGTR_LIBVO_MGA_ErrorInConfigIoctl "[MGA] error in mga_vid_config ioctl (wrong mga_vid.o version?)"
+#define MSGTR_LIBVO_MGA_CouldNotGetLumaValuesFromTheKernelModule "[MGA] Could not get luma values from the kernel module!\n"
+#define MSGTR_LIBVO_MGA_CouldNotSetLumaValuesFromTheKernelModule "[MGA] Could not set luma values from the kernel module!\n"
+#define MSGTR_LIBVO_MGA_ScreenWidthHeightUnknown "[MGA] Screen width/height unknown!\n"
+#define MSGTR_LIBVO_MGA_InvalidOutputFormat "[MGA] invalid output format %0X\n"
+#define MSGTR_LIBVO_MGA_IncompatibleDriverVersion "[MGA] Your mga_vid driver version is incompatible with this MPlayer version!\n"
+#define MSGTR_LIBVO_MGA_CouldntOpen "[MGA] Couldn't open: %s\n"
+#define MSGTR_LIBVO_MGA_ResolutionTooHigh "[MGA] Source resolution exceeds 1023x1023 in at least one dimension.\n[MGA] Rescale in software or use -lavdopts lowres=1.\n"
+#define MSGTR_LIBVO_MGA_mgavidVersionMismatch "[MGA] mismatch between kernel (%u) and MPlayer (%u) mga_vid driver versions\n"
+
+// vo_null.c
+#define MSGTR_LIBVO_NULL_UnknownSubdevice "[VO_NULL] Unknown subdevice: %s.\n"
+
+// vo_png.c
+#define MSGTR_LIBVO_PNG_Warning1 "[VO_PNG] Warning: compression level set to 0, compression disabled!\n"
+#define MSGTR_LIBVO_PNG_Warning2 "[VO_PNG] Info: Use -vo png:z=<n> to set compression level from 0 to 9.\n"
+#define MSGTR_LIBVO_PNG_Warning3 "[VO_PNG] Info: (0 = no compression, 1 = fastest, lowest - 9 best, slowest compression)\n"
+#define MSGTR_LIBVO_PNG_ErrorOpeningForWriting "\n[VO_PNG] Error opening '%s' for writing!\n"
+#define MSGTR_LIBVO_PNG_ErrorInCreatePng "[VO_PNG] Error in create_png.\n"
+
+// vo_pnm.c
+#define MSGTR_VO_PNM_ASCIIMode "ASCII mode enabled."
+#define MSGTR_VO_PNM_RawMode "Raw mode enabled."
+#define MSGTR_VO_PNM_PPMType "Will write PPM files."
+#define MSGTR_VO_PNM_PGMType "Will write PGM files."
+#define MSGTR_VO_PNM_PGMYUVType "Will write PGMYUV files."
+
+// vo_sdl.c
+#define MSGTR_LIBVO_SDL_CouldntGetAnyAcceptableSDLModeForOutput "[VO_SDL] Couldn't get any acceptable SDL Mode for output.\n"
+#define MSGTR_LIBVO_SDL_SetVideoModeFailed "[VO_SDL] set_video_mode: SDL_SetVideoMode failed: %s.\n"
+#define MSGTR_LIBVO_SDL_SetVideoModeFailedFull "[VO_SDL] Set_fullmode: SDL_SetVideoMode failed: %s.\n"
+#define MSGTR_LIBVO_SDL_MappingI420ToIYUV "[VO_SDL] Mapping I420 to IYUV.\n"
+#define MSGTR_LIBVO_SDL_UnsupportedImageFormat "[VO_SDL] Unsupported image format (0x%X).\n"
+#define MSGTR_LIBVO_SDL_InfoPleaseUseVmOrZoom "[VO_SDL] Info - please use -vm or -zoom to switch to the best resolution.\n"
+#define MSGTR_LIBVO_SDL_FailedToSetVideoMode "[VO_SDL] Failed to set video mode: %s.\n"
+#define MSGTR_LIBVO_SDL_CouldntCreateAYUVOverlay "[VO_SDL] Couldn't create a YUV overlay: %s.\n"
+#define MSGTR_LIBVO_SDL_CouldntCreateARGBSurface "[VO_SDL] Couldn't create an RGB surface: %s.\n"
+#define MSGTR_LIBVO_SDL_UsingDepthColorspaceConversion "[VO_SDL] Using depth/colorspace conversion, this will slow things down (%ibpp -> %ibpp).\n"
+#define MSGTR_LIBVO_SDL_UnsupportedImageFormatInDrawslice "[VO_SDL] Unsupported image format in draw_slice, contact MPlayer developers!\n"
+#define MSGTR_LIBVO_SDL_BlitFailed "[VO_SDL] Blit failed: %s.\n"
+#define MSGTR_LIBVO_SDL_InitializationFailed "[VO_SDL] SDL initialization failed: %s.\n"
+#define MSGTR_LIBVO_SDL_UsingDriver "[VO_SDL] Using driver: %s.\n"
+
+// vo_svga.c
+#define MSGTR_LIBVO_SVGA_ForcedVidmodeNotAvailable "[VO_SVGA] Forced vid_mode %d (%s) not available.\n"
+#define MSGTR_LIBVO_SVGA_ForcedVidmodeTooSmall "[VO_SVGA] Forced vid_mode %d (%s) too small.\n"
+#define MSGTR_LIBVO_SVGA_Vidmode "[VO_SVGA] Vid_mode: %d, %dx%d %dbpp.\n"
+#define MSGTR_LIBVO_SVGA_VgasetmodeFailed "[VO_SVGA] Vga_setmode(%d) failed.\n"
+#define MSGTR_LIBVO_SVGA_VideoModeIsLinearAndMemcpyCouldBeUsed "[VO_SVGA] Video mode is linear and memcpy could be used for image transfer.\n"
+#define MSGTR_LIBVO_SVGA_VideoModeHasHardwareAcceleration "[VO_SVGA] Video mode has hardware acceleration and put_image could be used.\n"
+#define MSGTR_LIBVO_SVGA_IfItWorksForYouIWouldLikeToKnow "[VO_SVGA] If it works for you I would like to know.\n[VO_SVGA] (send log with `mplayer test.avi -v -v -v -v &> svga.log`). Thx!\n"
+#define MSGTR_LIBVO_SVGA_VideoModeHas "[VO_SVGA] Video mode has %d page(s).\n"
+#define MSGTR_LIBVO_SVGA_CenteringImageStartAt "[VO_SVGA] Centering image. Starting at (%d,%d)\n"
+#define MSGTR_LIBVO_SVGA_UsingVidix "[VO_SVGA] Using VIDIX. w=%i h=%i mw=%i mh=%i\n"
+
+// vo_tdfx_vid.c
+#define MSGTR_LIBVO_TDFXVID_Move "[VO_TDXVID] Move %d(%d) x %d => %d.\n"
+#define MSGTR_LIBVO_TDFXVID_AGPMoveFailedToClearTheScreen "[VO_TDFXVID] AGP move failed to clear the screen.\n"
+#define MSGTR_LIBVO_TDFXVID_BlitFailed "[VO_TDFXVID] Blit failed.\n"
+#define MSGTR_LIBVO_TDFXVID_NonNativeOverlayFormatNeedConversion "[VO_TDFXVID] Non-native overlay format needs conversion.\n"
+#define MSGTR_LIBVO_TDFXVID_UnsupportedInputFormat "[VO_TDFXVID] Unsupported input format 0x%x.\n"
+#define MSGTR_LIBVO_TDFXVID_OverlaySetupFailed "[VO_TDFXVID] Overlay setup failed.\n"
+#define MSGTR_LIBVO_TDFXVID_OverlayOnFailed "[VO_TDFXVID] Overlay on failed.\n"
+#define MSGTR_LIBVO_TDFXVID_OverlayReady "[VO_TDFXVID] Overlay ready: %d(%d) x %d @ %d => %d(%d) x %d @ %d.\n"
+#define MSGTR_LIBVO_TDFXVID_TextureBlitReady "[VO_TDFXVID] Texture blit ready: %d(%d) x %d @ %d => %d(%d) x %d @ %d.\n"
+#define MSGTR_LIBVO_TDFXVID_OverlayOffFailed "[VO_TDFXVID] Overlay off failed\n"
+#define MSGTR_LIBVO_TDFXVID_CantOpen "[VO_TDFXVID] Can't open %s: %s.\n"
+#define MSGTR_LIBVO_TDFXVID_CantGetCurrentCfg "[VO_TDFXVID] Can't get current configuration: %s.\n"
+#define MSGTR_LIBVO_TDFXVID_MemmapFailed "[VO_TDFXVID] Memmap failed !!!!!\n"
+#define MSGTR_LIBVO_TDFXVID_GetImageTodo "Get image todo.\n"
+#define MSGTR_LIBVO_TDFXVID_AgpMoveFailed "[VO_TDFXVID] AGP move failed.\n"
+#define MSGTR_LIBVO_TDFXVID_SetYuvFailed "[VO_TDFXVID] Set YUV failed.\n"
+#define MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnYPlane "[VO_TDFXVID] AGP move failed on Y plane.\n"
+#define MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnUPlane "[VO_TDFXVID] AGP move failed on U plane.\n"
+#define MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnVPlane "[VO_TDFXVID] AGP move failed on V plane.\n"
+#define MSGTR_LIBVO_TDFXVID_UnknownFormat "[VO_TDFXVID] unknown format: 0x%x.\n"
+
+// vo_tdfxfb.c
+#define MSGTR_LIBVO_TDFXFB_CantOpen "[VO_TDFXFB] Can't open %s: %s.\n"
+#define MSGTR_LIBVO_TDFXFB_ProblemWithFbitgetFscreenInfo "[VO_TDFXFB] Problem with FBITGET_FSCREENINFO ioctl: %s.\n"
+#define MSGTR_LIBVO_TDFXFB_ProblemWithFbitgetVscreenInfo "[VO_TDFXFB] Problem with FBITGET_VSCREENINFO ioctl: %s.\n"
+#define MSGTR_LIBVO_TDFXFB_ThisDriverOnlySupports "[VO_TDFXFB] This driver only supports the 3Dfx Banshee, Voodoo3 and Voodoo 5.\n"
+#define MSGTR_LIBVO_TDFXFB_OutputIsNotSupported "[VO_TDFXFB] %d bpp output is not supported.\n"
+#define MSGTR_LIBVO_TDFXFB_CouldntMapMemoryAreas "[VO_TDFXFB] Couldn't map memory areas: %s.\n"
+#define MSGTR_LIBVO_TDFXFB_BppOutputIsNotSupported "[VO_TDFXFB] %d bpp output is not supported (This should never have happened).\n"
+#define MSGTR_LIBVO_TDFXFB_SomethingIsWrongWithControl "[VO_TDFXFB] Eik! Something's wrong with control().\n"
+#define MSGTR_LIBVO_TDFXFB_NotEnoughVideoMemoryToPlay "[VO_TDFXFB] Not enough video memory to play this movie. Try at a lower resolution.\n"
+#define MSGTR_LIBVO_TDFXFB_ScreenIs "[VO_TDFXFB] Screen is %dx%d at %d bpp, in is %dx%d at %d bpp, norm is %dx%d.\n"
+
+// vo_tga.c
+#define MSGTR_LIBVO_TGA_UnknownSubdevice "[VO_TGA] Unknown subdevice: %s.\n"
+
+// vo_vesa.c
+#define MSGTR_LIBVO_VESA_FatalErrorOccurred "[VO_VESA] Fatal error occurred! Can't continue.\n"
+#define MSGTR_LIBVO_VESA_UnknownSubdevice "[VO_VESA] unknown subdevice: '%s'.\n"
+#define MSGTR_LIBVO_VESA_YouHaveTooLittleVideoMemory "[VO_VESA] You have too little video memory for this mode:\n[VO_VESA] Required: %08lX present: %08lX.\n"
+#define MSGTR_LIBVO_VESA_YouHaveToSpecifyTheCapabilitiesOfTheMonitor "[VO_VESA] You have to specify the capabilities of the monitor. Not changing refresh rate.\n"
+#define MSGTR_LIBVO_VESA_UnableToFitTheMode "[VO_VESA] The mode does not fit the monitor limits. Not changing refresh rate.\n"
+#define MSGTR_LIBVO_VESA_DetectedInternalFatalError "[VO_VESA] Detected internal fatal error: init is called before preinit.\n"
+#define MSGTR_LIBVO_VESA_SwitchFlipIsNotSupported "[VO_VESA] The -flip option is not supported.\n"
+#define MSGTR_LIBVO_VESA_PossibleReasonNoVbe2BiosFound "[VO_VESA] Possible reason: No VBE2 BIOS found.\n"
+#define MSGTR_LIBVO_VESA_FoundVesaVbeBiosVersion "[VO_VESA] Found VESA VBE BIOS Version %x.%x Revision: %x.\n"
+#define MSGTR_LIBVO_VESA_VideoMemory "[VO_VESA] Video memory: %u Kb.\n"
+#define MSGTR_LIBVO_VESA_Capabilites "[VO_VESA] VESA Capabilities: %s %s %s %s %s.\n"
+#define MSGTR_LIBVO_VESA_BelowWillBePrintedOemInfo "[VO_VESA] !!! OEM info will be printed below !!!\n"
+#define MSGTR_LIBVO_VESA_YouShouldSee5OemRelatedLines "[VO_VESA] You should see 5 OEM related lines below; If not, you've broken vm86.\n"
+#define MSGTR_LIBVO_VESA_OemInfo "[VO_VESA] OEM info: %s.\n"
+#define MSGTR_LIBVO_VESA_OemRevision "[VO_VESA] OEM Revision: %x.\n"
+#define MSGTR_LIBVO_VESA_OemVendor "[VO_VESA] OEM vendor: %s.\n"
+#define MSGTR_LIBVO_VESA_OemProductName "[VO_VESA] OEM Product Name: %s.\n"
+#define MSGTR_LIBVO_VESA_OemProductRev "[VO_VESA] OEM Product Rev: %s.\n"
+#define MSGTR_LIBVO_VESA_Hint "[VO_VESA] Hint: For working TV-Out you should have plugged in the TV connector\n"\
+"[VO_VESA] before booting since VESA BIOS initializes itself only during POST.\n"
+#define MSGTR_LIBVO_VESA_UsingVesaMode "[VO_VESA] Using VESA mode (%u) = %x [%ux%u@%u]\n"
+#define MSGTR_LIBVO_VESA_CantInitializeSwscaler "[VO_VESA] Can't initialize software scaler.\n"
+#define MSGTR_LIBVO_VESA_CantUseDga "[VO_VESA] Can't use DGA. Force bank switching mode. :(\n"
+#define MSGTR_LIBVO_VESA_UsingDga "[VO_VESA] Using DGA (physical resources: %08lXh, %08lXh)"
+#define MSGTR_LIBVO_VESA_CantUseDoubleBuffering "[VO_VESA] Can't use double buffering: not enough video memory.\n"
+#define MSGTR_LIBVO_VESA_CantFindNeitherDga "[VO_VESA] Can find neither DGA nor relocatable window frame.\n"
+#define MSGTR_LIBVO_VESA_YouveForcedDga "[VO_VESA] You've forced DGA. Exiting\n"
+#define MSGTR_LIBVO_VESA_CantFindValidWindowAddress "[VO_VESA] Can't find valid window address.\n"
+#define MSGTR_LIBVO_VESA_UsingBankSwitchingMode "[VO_VESA] Using bank switching mode (physical resources: %08lXh, %08lXh).\n"
+#define MSGTR_LIBVO_VESA_CantAllocateTemporaryBuffer "[VO_VESA] Can't allocate temporary buffer.\n"
+#define MSGTR_LIBVO_VESA_SorryUnsupportedMode "[VO_VESA] Sorry, unsupported mode -- try -x 640 -zoom.\n"
+#define MSGTR_LIBVO_VESA_OhYouReallyHavePictureOnTv "[VO_VESA] Oh you really have a picture on the TV!\n"
+#define MSGTR_LIBVO_VESA_CantInitialozeLinuxVideoOverlay "[VO_VESA] Can't initialize Linux Video Overlay.\n"
+#define MSGTR_LIBVO_VESA_UsingVideoOverlay "[VO_VESA] Using video overlay: %s.\n"
+#define MSGTR_LIBVO_VESA_CantInitializeVidixDriver "[VO_VESA] Can't initialize VIDIX driver.\n"
+#define MSGTR_LIBVO_VESA_UsingVidix "[VO_VESA] Using VIDIX.\n"
+#define MSGTR_LIBVO_VESA_CantFindModeFor "[VO_VESA] Can't find mode for: %ux%u@%u.\n"
+#define MSGTR_LIBVO_VESA_InitializationComplete "[VO_VESA] VESA initialization complete.\n"
+
+// vesa_lvo.c
+#define MSGTR_LIBVO_VESA_ThisBranchIsNoLongerSupported "[VESA_LVO] This branch is no longer supported.\n[VESA_LVO] Please use -vo vesa:vidix instead.\n"
+#define MSGTR_LIBVO_VESA_CouldntOpen "[VESA_LVO] Couldn't open: '%s'\n"
+#define MSGTR_LIBVO_VESA_InvalidOutputFormat "[VESA_LVI] Invalid output format: %s(%0X)\n"
+#define MSGTR_LIBVO_VESA_IncompatibleDriverVersion "[VESA_LVO] Your fb_vid driver version is incompatible with this MPlayer version!\n"
+
+// vo_x11.c
+#define MSGTR_LIBVO_X11_DrawFrameCalled "[VO_X11] draw_frame() called!!!!!!\n"
+
+// vo_xv.c
+#define MSGTR_LIBVO_XV_DrawFrameCalled "[VO_XV] draw_frame() called!!!!!!\n"
+#define MSGTR_LIBVO_XV_SharedMemoryNotSupported "[VO_XV] Shared memory not supported\nReverting to normal Xv.\n"
+#define MSGTR_LIBVO_XV_XvNotSupportedByX11 "[VO_XV] Sorry, Xv not supported by this X11 version/driver\n[VO_XV] ******** Try with -vo x11 or -vo sdl *********\n"
+#define MSGTR_LIBVO_XV_XvQueryAdaptorsFailed "[VO_XV] XvQueryAdaptors failed.\n"
+#define MSGTR_LIBVO_XV_InvalidPortParameter "[VO_XV] Invalid port parameter, overriding with port 0.\n"
+#define MSGTR_LIBVO_XV_CouldNotGrabPort "[VO_XV] Could not grab port %i.\n"
+#define MSGTR_LIBVO_XV_CouldNotFindFreePort "[VO_XV] Could not find free Xvideo port - maybe another process is already\n"\
+"[VO_XV] using it. Close all video applications, and try again. If that does\n"\
+"[VO_XV] not help, see 'mplayer -vo help' for other (non-xv) video out drivers.\n"
+#define MSGTR_LIBVO_XV_NoXvideoSupport "[VO_XV] It seems there is no Xvideo support for your video card available.\n"\
+"[VO_XV] Run 'xvinfo' to verify its Xv support and read\n"\
+"[VO_XV] DOCS/HTML/en/video.html#xv!\n"\
+"[VO_XV] See 'mplayer -vo help' for other (non-xv) video out drivers.\n"\
+"[VO_XV] Try -vo x11.\n"
+#define MSGTR_VO_XV_ImagedimTooHigh "Source image dimensions are too high: %ux%u (maximum is %ux%u)\n"
+
+// vo_yuv4mpeg.c
+#define MSGTR_VO_YUV4MPEG_InterlacedHeightDivisibleBy4 "Interlaced mode requires image height to be divisible by 4."
+#define MSGTR_VO_YUV4MPEG_InterlacedLineBufAllocFail "Unable to allocate line buffer for interlaced mode."
+#define MSGTR_VO_YUV4MPEG_WidthDivisibleBy2 "Image width must be divisible by 2."
+#define MSGTR_VO_YUV4MPEG_OutFileOpenError "Can't get memory or file handle to write \"%s\"!"
+#define MSGTR_VO_YUV4MPEG_OutFileWriteError "Error writing image to output!"
+#define MSGTR_VO_YUV4MPEG_UnknownSubDev "Unknown subdevice: %s"
+#define MSGTR_VO_YUV4MPEG_InterlacedTFFMode "Using interlaced output mode, top-field first."
+#define MSGTR_VO_YUV4MPEG_InterlacedBFFMode "Using interlaced output mode, bottom-field first."
+#define MSGTR_VO_YUV4MPEG_ProgressiveMode "Using (default) progressive frame mode."
+
+// vosub_vidix.c
+#define MSGTR_LIBVO_SUB_VIDIX_CantStartPlayback "[VO_SUB_VIDIX] Can't start playback: %s\n"
+#define MSGTR_LIBVO_SUB_VIDIX_CantStopPlayback "[VO_SUB_VIDIX] Can't stop playback: %s\n"
+#define MSGTR_LIBVO_SUB_VIDIX_InterleavedUvForYuv410pNotSupported "[VO_SUB_VIDIX] Interleaved UV for YUV410P not supported.\n"
+#define MSGTR_LIBVO_SUB_VIDIX_DummyVidixdrawsliceWasCalled "[VO_SUB_VIDIX] Dummy vidix_draw_slice() was called.\n"
+#define MSGTR_LIBVO_SUB_VIDIX_DummyVidixdrawframeWasCalled "[VO_SUB_VIDIX] Dummy vidix_draw_frame() was called.\n"
+#define MSGTR_LIBVO_SUB_VIDIX_UnsupportedFourccForThisVidixDriver "[VO_SUB_VIDIX] Unsupported FourCC for this VIDIX driver: %x (%s).\n"
+#define MSGTR_LIBVO_SUB_VIDIX_VideoServerHasUnsupportedResolution "[VO_SUB_VIDIX] Video server has unsupported resolution (%dx%d), supported: %dx%d-%dx%d.\n"
+#define MSGTR_LIBVO_SUB_VIDIX_VideoServerHasUnsupportedColorDepth "[VO_SUB_VIDIX] Video server has unsupported color depth by vidix (%d).\n"
+#define MSGTR_LIBVO_SUB_VIDIX_DriverCantUpscaleImage "[VO_SUB_VIDIX] VIDIX driver can't upscale image (%d%d -> %d%d).\n"
+#define MSGTR_LIBVO_SUB_VIDIX_DriverCantDownscaleImage "[VO_SUB_VIDIX] VIDIX driver can't downscale image (%d%d -> %d%d).\n"
+#define MSGTR_LIBVO_SUB_VIDIX_CantConfigurePlayback "[VO_SUB_VIDIX] Can't configure playback: %s.\n"
+#define MSGTR_LIBVO_SUB_VIDIX_YouHaveWrongVersionOfVidixLibrary "[VO_SUB_VIDIX] You have the wrong version of the VIDIX library.\n"
+#define MSGTR_LIBVO_SUB_VIDIX_CouldntFindWorkingVidixDriver "[VO_SUB_VIDIX] Couldn't find working VIDIX driver.\n"
+#define MSGTR_LIBVO_SUB_VIDIX_CouldntGetCapability "[VO_SUB_VIDIX] Couldn't get capability: %s.\n"
+
+// x11_common.c
+#define MSGTR_EwmhFullscreenStateFailed "\nX11: Couldn't send EWMH fullscreen event!\n"
+#define MSGTR_CouldNotFindXScreenSaver "xscreensaver_disable: Could not find XScreenSaver window.\n"
+#define MSGTR_SelectedVideoMode "XF86VM: Selected video mode %dx%d for image size %dx%d.\n"
+
+#define MSGTR_InsertingAfVolume "[Mixer] No hardware mixing, inserting volume filter.\n"
+#define MSGTR_NoVolume "[Mixer] No volume control available.\n"
+#define MSGTR_NoBalance "[Mixer] No balance control available.\n"
+
+// old vo drivers that have been replaced
+#define MSGTR_VO_PGM_HasBeenReplaced "The pgm video output driver has been replaced by -vo pnm:pgmyuv.\n"
+#define MSGTR_VO_MD5_HasBeenReplaced "The md5 video output driver has been replaced by -vo md5sum.\n"
+
+
+// ======================= audio output drivers ========================
+
+// audio_out.c
+#define MSGTR_AO_ALSA9_1x_Removed "audio_out: alsa9 and alsa1x modules were removed, use -ao alsa instead.\n"
+#define MSGTR_AO_TryingPreferredAudioDriver "Trying preferred audio driver '%.*s', options '%s'\n"
+#define MSGTR_AO_NoSuchDriver "No such audio driver '%.*s'\n"
+#define MSGTR_AO_FailedInit "Failed to initialize audio driver '%s'\n"
+#define MSGTR_AO_TryingEveryKnown "Trying every known audio driver...\n"
+
+// ao_oss.c
+#define MSGTR_AO_OSS_CantOpenMixer "[AO OSS] audio_setup: Can't open mixer device %s: %s\n"
+#define MSGTR_AO_OSS_ChanNotFound "[AO OSS] audio_setup: Audio card mixer does not have channel '%s', using default.\n"
+#define MSGTR_AO_OSS_CantOpenDev "[AO OSS] audio_setup: Can't open audio device %s: %s\n"
+#define MSGTR_AO_OSS_CantMakeFd "[AO OSS] audio_setup: Can't make file descriptor blocking: %s\n"
+#define MSGTR_AO_OSS_CantSet "[AO OSS] Can't set audio device %s to %s output, trying %s...\n"
+#define MSGTR_AO_OSS_CantSetChans "[AO OSS] audio_setup: Failed to set audio device to %d channels.\n"
+#define MSGTR_AO_OSS_CantUseGetospace "[AO OSS] audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n"
+#define MSGTR_AO_OSS_CantUseSelect "[AO OSS]\n *** Your audio driver DOES NOT support select() ***\n Recompile MPlayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n"
+#define MSGTR_AO_OSS_CantReopen "[AO OSS]\nFatal error: *** CANNOT RE-OPEN / RESET AUDIO DEVICE *** %s\n"
+#define MSGTR_AO_OSS_UnknownUnsupportedFormat "[AO OSS] Unknown/Unsupported OSS format: %x.\n"
+
+// ao_arts.c
+#define MSGTR_AO_ARTS_CantInit "[AO ARTS] %s\n"
+#define MSGTR_AO_ARTS_ServerConnect "[AO ARTS] Connected to sound server.\n"
+#define MSGTR_AO_ARTS_CantOpenStream "[AO ARTS] Unable to open a stream.\n"
+#define MSGTR_AO_ARTS_StreamOpen "[AO ARTS] Stream opened.\n"
+#define MSGTR_AO_ARTS_BufferSize "[AO ARTS] buffer size: %d\n"
+
+// ao_dxr2.c
+#define MSGTR_AO_DXR2_SetVolFailed "[AO DXR2] Setting volume to %d failed.\n"
+#define MSGTR_AO_DXR2_UnsupSamplerate "[AO DXR2] %d Hz not supported, try to resample.\n"
+
+// ao_esd.c
+#define MSGTR_AO_ESD_CantOpenSound "[AO ESD] esd_open_sound failed: %s\n"
+#define MSGTR_AO_ESD_LatencyInfo "[AO ESD] latency: [server: %0.2fs, net: %0.2fs] (adjust %0.2fs)\n"
+#define MSGTR_AO_ESD_CantOpenPBStream "[AO ESD] failed to open ESD playback stream: %s\n"
+
+// ao_mpegpes.c
+#define MSGTR_AO_MPEGPES_CantSetMixer "[AO MPEGPES] DVB audio set mixer failed: %s.\n"
+#define MSGTR_AO_MPEGPES_UnsupSamplerate "[AO MPEGPES] %d Hz not supported, try to resample.\n"
+
+// ao_pcm.c
+#define MSGTR_AO_PCM_FileInfo "[AO PCM] File: %s (%s)\nPCM: Samplerate: %iHz Channels: %s Format %s\n"
+#define MSGTR_AO_PCM_HintInfo "[AO PCM] Info: Faster dumping is achieved with -vc null -vo null -ao pcm:fast\n[AO PCM] Info: To write WAVE files use -ao pcm:waveheader (default).\n"
+#define MSGTR_AO_PCM_CantOpenOutputFile "[AO PCM] Failed to open %s for writing!\n"
+
+// ao_sdl.c
+#define MSGTR_AO_SDL_INFO "[AO SDL] Samplerate: %iHz Channels: %s Format %s\n"
+#define MSGTR_AO_SDL_DriverInfo "[AO SDL] using %s audio driver.\n"
+#define MSGTR_AO_SDL_UnsupportedAudioFmt "[AO SDL] Unsupported audio format: 0x%x.\n"
+#define MSGTR_AO_SDL_CantInit "[AO SDL] SDL Audio initialization failed: %s\n"
+#define MSGTR_AO_SDL_CantOpenAudio "[AO SDL] Unable to open audio: %s\n"
+
+// ao_sgi.c
+#define MSGTR_AO_SGI_INFO "[AO SGI] control.\n"
+#define MSGTR_AO_SGI_InitInfo "[AO SGI] init: Samplerate: %iHz Channels: %s Format %s\n"
+#define MSGTR_AO_SGI_InvalidDevice "[AO SGI] play: invalid device.\n"
+#define MSGTR_AO_SGI_CantSetParms_Samplerate "[AO SGI] init: setparams failed: %s\nCould not set desired samplerate.\n"
+#define MSGTR_AO_SGI_CantSetAlRate "[AO SGI] init: AL_RATE was not accepted on the given resource.\n"
+#define MSGTR_AO_SGI_CantGetParms "[AO SGI] init: getparams failed: %s\n"
+#define MSGTR_AO_SGI_SampleRateInfo "[AO SGI] init: samplerate is now %lf (desired rate is %lf)\n"
+#define MSGTR_AO_SGI_InitConfigError "[AO SGI] init: %s\n"
+#define MSGTR_AO_SGI_InitOpenAudioFailed "[AO SGI] init: Unable to open audio channel: %s\n"
+#define MSGTR_AO_SGI_Uninit "[AO SGI] uninit: ...\n"
+#define MSGTR_AO_SGI_Reset "[AO SGI] reset: ...\n"
+#define MSGTR_AO_SGI_PauseInfo "[AO SGI] audio_pause: ...\n"
+#define MSGTR_AO_SGI_ResumeInfo "[AO SGI] audio_resume: ...\n"
+
+// ao_sun.c
+#define MSGTR_AO_SUN_RtscSetinfoFailed "[AO SUN] rtsc: SETINFO failed.\n"
+#define MSGTR_AO_SUN_RtscWriteFailed "[AO SUN] rtsc: write failed.\n"
+#define MSGTR_AO_SUN_CantOpenAudioDev "[AO SUN] Can't open audio device %s, %s -> nosound.\n"
+#define MSGTR_AO_SUN_UnsupSampleRate "[AO SUN] audio_setup: your card doesn't support %d channel, %s, %d Hz samplerate.\n"
+#define MSGTR_AO_SUN_CantUseSelect "[AO SUN]\n *** Your audio driver DOES NOT support select() ***\nRecompile MPlayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n"
+#define MSGTR_AO_SUN_CantReopenReset "[AO SUN]\nFatal error: *** CANNOT REOPEN / RESET AUDIO DEVICE (%s) ***\n"
+
+// ao_alsa5.c
+#define MSGTR_AO_ALSA5_InitInfo "[AO ALSA5] alsa-init: requested format: %d Hz, %d channels, %s\n"
+#define MSGTR_AO_ALSA5_SoundCardNotFound "[AO ALSA5] alsa-init: no soundcards found.\n"
+#define MSGTR_AO_ALSA5_InvalidFormatReq "[AO ALSA5] alsa-init: invalid format (%s) requested - output disabled.\n"
+#define MSGTR_AO_ALSA5_PlayBackError "[AO ALSA5] alsa-init: playback open error: %s\n"
+#define MSGTR_AO_ALSA5_PcmInfoError "[AO ALSA5] alsa-init: PCM info error: %s\n"
+#define MSGTR_AO_ALSA5_SoundcardsFound "[AO ALSA5] alsa-init: %d soundcard(s) found, using: %s\n"
+#define MSGTR_AO_ALSA5_PcmChanInfoError "[AO ALSA5] alsa-init: PCM channel info error: %s\n"
+#define MSGTR_AO_ALSA5_CantSetParms "[AO ALSA5] alsa-init: error setting parameters: %s\n"
+#define MSGTR_AO_ALSA5_CantSetChan "[AO ALSA5] alsa-init: error setting up channel: %s\n"
+#define MSGTR_AO_ALSA5_ChanPrepareError "[AO ALSA5] alsa-init: channel prepare error: %s\n"
+#define MSGTR_AO_ALSA5_DrainError "[AO ALSA5] alsa-uninit: playback drain error: %s\n"
+#define MSGTR_AO_ALSA5_FlushError "[AO ALSA5] alsa-uninit: playback flush error: %s\n"
+#define MSGTR_AO_ALSA5_PcmCloseError "[AO ALSA5] alsa-uninit: PCM close error: %s\n"
+#define MSGTR_AO_ALSA5_ResetDrainError "[AO ALSA5] alsa-reset: playback drain error: %s\n"
+#define MSGTR_AO_ALSA5_ResetFlushError "[AO ALSA5] alsa-reset: playback flush error: %s\n"
+#define MSGTR_AO_ALSA5_ResetChanPrepareError "[AO ALSA5] alsa-reset: channel prepare error: %s\n"
+#define MSGTR_AO_ALSA5_PauseDrainError "[AO ALSA5] alsa-pause: playback drain error: %s\n"
+#define MSGTR_AO_ALSA5_PauseFlushError "[AO ALSA5] alsa-pause: playback flush error: %s\n"
+#define MSGTR_AO_ALSA5_ResumePrepareError "[AO ALSA5] alsa-resume: channel prepare error: %s\n"
+#define MSGTR_AO_ALSA5_Underrun "[AO ALSA5] alsa-play: alsa underrun, resetting stream.\n"
+#define MSGTR_AO_ALSA5_PlaybackPrepareError "[AO ALSA5] alsa-play: playback prepare error: %s\n"
+#define MSGTR_AO_ALSA5_WriteErrorAfterReset "[AO ALSA5] alsa-play: write error after reset: %s - giving up.\n"
+#define MSGTR_AO_ALSA5_OutPutError "[AO ALSA5] alsa-play: output error: %s\n"
+
+// ao_alsa.c
+#define MSGTR_AO_ALSA_InvalidMixerIndexDefaultingToZero "[AO_ALSA] Invalid mixer index. Defaulting to 0.\n"
+#define MSGTR_AO_ALSA_MixerOpenError "[AO_ALSA] Mixer open error: %s\n"
+#define MSGTR_AO_ALSA_MixerAttachError "[AO_ALSA] Mixer attach %s error: %s\n"
+#define MSGTR_AO_ALSA_MixerRegisterError "[AO_ALSA] Mixer register error: %s\n"
+#define MSGTR_AO_ALSA_MixerLoadError "[AO_ALSA] Mixer load error: %s\n"
+#define MSGTR_AO_ALSA_UnableToFindSimpleControl "[AO_ALSA] Unable to find simple control '%s',%i.\n"
+#define MSGTR_AO_ALSA_ErrorSettingLeftChannel "[AO_ALSA] Error setting left channel, %s\n"
+#define MSGTR_AO_ALSA_ErrorSettingRightChannel "[AO_ALSA] Error setting right channel, %s\n"
+#define MSGTR_AO_ALSA_CommandlineHelp "\n[AO_ALSA] -ao alsa commandline help:\n"\
+"[AO_ALSA] Example: mplayer -ao alsa:device=hw=0.3\n"\
+"[AO_ALSA] Sets first card fourth hardware device.\n\n"\
+"[AO_ALSA] Options:\n"\
+"[AO_ALSA] noblock\n"\
+"[AO_ALSA] Opens device in non-blocking mode.\n"\
+"[AO_ALSA] device=<device-name>\n"\
+"[AO_ALSA] Sets device (change , to . and : to =)\n"
+#define MSGTR_AO_ALSA_ChannelsNotSupported "[AO_ALSA] %d channels are not supported.\n"
+#define MSGTR_AO_ALSA_OpenInNonblockModeFailed "[AO_ALSA] Open in nonblock-mode failed, trying to open in block-mode.\n"
+#define MSGTR_AO_ALSA_PlaybackOpenError "[AO_ALSA] Playback open error: %s\n"
+#define MSGTR_AO_ALSA_ErrorSetBlockMode "[AL_ALSA] Error setting block-mode %s.\n"
+#define MSGTR_AO_ALSA_UnableToGetInitialParameters "[AO_ALSA] Unable to get initial parameters: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetAccessType "[AO_ALSA] Unable to set access type: %s\n"
+#define MSGTR_AO_ALSA_FormatNotSupportedByHardware "[AO_ALSA] Format %s is not supported by hardware, trying default.\n"
+#define MSGTR_AO_ALSA_UnableToSetFormat "[AO_ALSA] Unable to set format: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetChannels "[AO_ALSA] Unable to set channels: %s\n"
+#define MSGTR_AO_ALSA_UnableToDisableResampling "[AO_ALSA] Unable to disable resampling: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetSamplerate2 "[AO_ALSA] Unable to set samplerate-2: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetBufferTimeNear "[AO_ALSA] Unable to set buffer time near: %s\n"
+#define MSGTR_AO_ALSA_UnableToGetPeriodSize "[AO ALSA] Unable to get period size: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetPeriods "[AO_ALSA] Unable to set periods: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetHwParameters "[AO_ALSA] Unable to set hw-parameters: %s\n"
+#define MSGTR_AO_ALSA_UnableToGetBufferSize "[AO_ALSA] Unable to get buffersize: %s\n"
+#define MSGTR_AO_ALSA_UnableToGetSwParameters "[AO_ALSA] Unable to get sw-parameters: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetSwParameters "[AO_ALSA] Unable to set sw-parameters: %s\n"
+#define MSGTR_AO_ALSA_UnableToGetBoundary "[AO_ALSA] Unable to get boundary: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetStartThreshold "[AO_ALSA] Unable to set start threshold: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetStopThreshold "[AO_ALSA] Unable to set stop threshold: %s\n"
+#define MSGTR_AO_ALSA_UnableToSetSilenceSize "[AO_ALSA] Unable to set silence size: %s\n"
+#define MSGTR_AO_ALSA_PcmCloseError "[AO_ALSA] pcm close error: %s\n"
+#define MSGTR_AO_ALSA_NoHandlerDefined "[AO_ALSA] No handler defined!\n"
+#define MSGTR_AO_ALSA_PcmPrepareError "[AO_ALSA] pcm prepare error: %s\n"
+#define MSGTR_AO_ALSA_PcmPauseError "[AO_ALSA] pcm pause error: %s\n"
+#define MSGTR_AO_ALSA_PcmDropError "[AO_ALSA] pcm drop error: %s\n"
+#define MSGTR_AO_ALSA_PcmResumeError "[AO_ALSA] pcm resume error: %s\n"
+#define MSGTR_AO_ALSA_DeviceConfigurationError "[AO_ALSA] Device configuration error."
+#define MSGTR_AO_ALSA_PcmInSuspendModeTryingResume "[AO_ALSA] Pcm in suspend mode, trying to resume.\n"
+#define MSGTR_AO_ALSA_WriteError "[AO_ALSA] Write error: %s\n"
+#define MSGTR_AO_ALSA_TryingToResetSoundcard "[AO_ALSA] Trying to reset soundcard.\n"
+#define MSGTR_AO_ALSA_CannotGetPcmStatus "[AO_ALSA] Cannot get pcm status: %s\n"
+
+// ao_plugin.c
+#define MSGTR_AO_PLUGIN_InvalidPlugin "[AO PLUGIN] invalid plugin: %s\n"
+
+
+// ======================= audio filters ================================
+
+// af_scaletempo.c
+#define MSGTR_AF_ValueOutOfRange MSGTR_VO_ValueOutOfRange
+
+// af_ladspa.c
+#define MSGTR_AF_LADSPA_AvailableLabels "available labels in"
+#define MSGTR_AF_LADSPA_WarnNoInputs "WARNING! This LADSPA plugin has no audio inputs.\n The incoming audio signal will be lost."
+#define MSGTR_AF_LADSPA_ErrMultiChannel "Multi-channel (>2) plugins are not supported (yet).\n Use only mono and stereo plugins."
+#define MSGTR_AF_LADSPA_ErrNoOutputs "This LADSPA plugin has no audio outputs."
+#define MSGTR_AF_LADSPA_ErrInOutDiff "The number of audio inputs and audio outputs of the LADSPA plugin differ."
+#define MSGTR_AF_LADSPA_ErrFailedToLoad "failed to load"
+#define MSGTR_AF_LADSPA_ErrNoDescriptor "Couldn't find ladspa_descriptor() function in the specified library file."
+#define MSGTR_AF_LADSPA_ErrLabelNotFound "Couldn't find label in plugin library."
+#define MSGTR_AF_LADSPA_ErrNoSuboptions "No suboptions specified."
+#define MSGTR_AF_LADSPA_ErrNoLibFile "No library file specified."
+#define MSGTR_AF_LADSPA_ErrNoLabel "No filter label specified."
+#define MSGTR_AF_LADSPA_ErrNotEnoughControls "Not enough controls specified on the command line."
+#define MSGTR_AF_LADSPA_ErrControlBelow "%s: Input control #%d is below lower boundary of %0.4f.\n"
+#define MSGTR_AF_LADSPA_ErrControlAbove "%s: Input control #%d is above upper boundary of %0.4f.\n"
+
+// format.c
+#define MSGTR_AF_FORMAT_UnknownFormat "unknown format "
+
+
+// ========================== INPUT =========================================
+
+// joystick.c
+#define MSGTR_INPUT_JOYSTICK_Opening "Opening joystick device %s\n"
+#define MSGTR_INPUT_JOYSTICK_CantOpen "Can't open joystick device %s: %s\n"
+#define MSGTR_INPUT_JOYSTICK_ErrReading "Error while reading joystick device: %s\n"
+#define MSGTR_INPUT_JOYSTICK_LoosingBytes "Joystick: We lose %d bytes of data\n"
+#define MSGTR_INPUT_JOYSTICK_WarnLostSync "Joystick: warning init event, we have lost sync with driver.\n"
+#define MSGTR_INPUT_JOYSTICK_WarnUnknownEvent "Joystick warning unknown event type %d\n"
+
+// appleir.c
+#define MSGTR_INPUT_APPLE_IR_Init "Initializing Apple IR on %s\n"
+#define MSGTR_INPUT_APPLE_IR_Detect "Detected Apple IR on %s\n"
+#define MSGTR_INPUT_APPLE_IR_CantOpen "Can't open Apple IR device: %s\n"
+
+// input.c
+#define MSGTR_INPUT_INPUT_ErrCantRegister2ManyCmdFds "Too many command file descriptors, cannot register file descriptor %d.\n"
+#define MSGTR_INPUT_INPUT_ErrCantRegister2ManyKeyFds "Too many key file descriptors, cannot register file descriptor %d.\n"
+#define MSGTR_INPUT_INPUT_ErrArgMustBeInt "Command %s: argument %d isn't an integer.\n"
+#define MSGTR_INPUT_INPUT_ErrArgMustBeFloat "Command %s: argument %d isn't a float.\n"
+#define MSGTR_INPUT_INPUT_ErrUnterminatedArg "Command %s: argument %d is unterminated.\n"
+#define MSGTR_INPUT_INPUT_ErrUnknownArg "Unknown argument %d\n"
+#define MSGTR_INPUT_INPUT_Err2FewArgs "Command %s requires at least %d arguments, we found only %d so far.\n"
+#define MSGTR_INPUT_INPUT_ErrReadingCmdFd "Error while reading command file descriptor %d: %s\n"
+#define MSGTR_INPUT_INPUT_ErrCmdBufferFullDroppingContent "Command buffer of file descriptor %d is full: dropping content.\n"
+#define MSGTR_INPUT_INPUT_ErrInvalidCommandForKey "Invalid command for bound key %s"
+#define MSGTR_INPUT_INPUT_ErrSelect "Select error: %s\n"
+#define MSGTR_INPUT_INPUT_ErrOnKeyInFd "Error on key input file descriptor %d\n"
+#define MSGTR_INPUT_INPUT_ErrDeadKeyOnFd "Dead key input on file descriptor %d\n"
+#define MSGTR_INPUT_INPUT_Err2ManyKeyDowns "Too many key down events at the same time\n"
+#define MSGTR_INPUT_INPUT_ErrOnCmdFd "Error on command file descriptor %d\n"
+#define MSGTR_INPUT_INPUT_ErrReadingInputConfig "Error while reading input config file %s: %s\n"
+#define MSGTR_INPUT_INPUT_ErrUnknownKey "Unknown key '%s'\n"
+#define MSGTR_INPUT_INPUT_ErrUnfinishedBinding "Unfinished binding %s\n"
+#define MSGTR_INPUT_INPUT_ErrBuffer2SmallForKeyName "Buffer is too small for this key name: %s\n"
+#define MSGTR_INPUT_INPUT_ErrNoCmdForKey "No command found for key %s"
+#define MSGTR_INPUT_INPUT_ErrBuffer2SmallForCmd "Buffer is too small for command %s\n"
+#define MSGTR_INPUT_INPUT_ErrWhyHere "What are we doing here?\n"
+#define MSGTR_INPUT_INPUT_ErrCantInitJoystick "Can't init input joystick\n"
+#define MSGTR_INPUT_INPUT_ErrCantStatFile "Can't stat %s: %s\n"
+#define MSGTR_INPUT_INPUT_ErrCantOpenFile "Can't open %s: %s\n"
+#define MSGTR_INPUT_INPUT_ErrCantInitAppleRemote "Can't init Apple Remote.\n"
+
+// lirc.c
+#define MSGTR_SettingUpLIRC "Setting up LIRC support...\n"
+#define MSGTR_LIRCopenfailed "Failed to open LIRC support. You will not be able to use your remote control.\n"
+#define MSGTR_LIRCcfgerr "Failed to read LIRC config file %s.\n"
+
+
+// ========================== LIBMPDEMUX ===================================
+
+// muxer.c, muxer_*.c
+#define MSGTR_TooManyStreams "Too many streams!"
+#define MSGTR_RawMuxerOnlyOneStream "Rawaudio muxer supports only one audio stream!\n"
+#define MSGTR_IgnoringVideoStream "Ignoring video stream!\n"
+#define MSGTR_UnknownStreamType "Warning, unknown stream type: %d\n"
+#define MSGTR_WarningLenIsntDivisible "Warning, len isn't divisible by samplesize!\n"
+#define MSGTR_MuxbufMallocErr "Muxer frame buffer cannot allocate memory!\n"
+#define MSGTR_MuxbufReallocErr "Muxer frame buffer cannot reallocate memory!\n"
+#define MSGTR_MuxbufSending "Muxer frame buffer sending %d frame(s) to the muxer.\n"
+#define MSGTR_WritingHeader "Writing header...\n"
+#define MSGTR_WritingTrailer "Writing index...\n"
+
+// demuxer.c, demux_*.c
+#define MSGTR_AudioStreamRedefined "WARNING: Audio stream header %d redefined.\n"
+#define MSGTR_VideoStreamRedefined "WARNING: Video stream header %d redefined.\n"
+#define MSGTR_TooManyAudioInBuffer "\nToo many audio packets in the buffer: (%d in %d bytes).\n"
+#define MSGTR_TooManyVideoInBuffer "\nToo many video packets in the buffer: (%d in %d bytes).\n"
+#define MSGTR_MaybeNI "Maybe you are playing a non-interleaved stream/file or the codec failed?\n" \
+ "For AVI files, try to force non-interleaved mode with the -ni option.\n"
+#define MSGTR_WorkAroundBlockAlignHeaderBug "AVI: Working around CBR-MP3 nBlockAlign header bug!\n"
+#define MSGTR_SwitchToNi "\nBadly interleaved AVI file detected - switching to -ni mode...\n"
+#define MSGTR_InvalidAudioStreamNosound "AVI: invalid audio stream ID: %d - ignoring (nosound)\n"
+#define MSGTR_InvalidAudioStreamUsingDefault "AVI: invalid video stream ID: %d - ignoring (using default)\n"
+#define MSGTR_ON2AviFormat "ON2 AVI format"
+#define MSGTR_Detected_XXX_FileFormat "%s file format detected.\n"
+#define MSGTR_DetectedAudiofile "Audio file detected.\n"
+#define MSGTR_NotSystemStream "Not MPEG System Stream format... (maybe Transport Stream?)\n"
+#define MSGTR_InvalidMPEGES "Invalid MPEG-ES stream??? Contact the author, it may be a bug :(\n"
+#define MSGTR_FormatNotRecognized "============ Sorry, this file format is not recognized/supported =============\n"\
+ "=== If this file is an AVI, ASF or MPEG stream, please contact the author! ===\n"
+#define MSGTR_SettingProcessPriority "Setting process priority: %s\n"
+#define MSGTR_FilefmtFourccSizeFpsFtime "[V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.3f ftime:=%6.4f\n"
+#define MSGTR_CannotInitializeMuxer "Cannot initialize muxer."
+#define MSGTR_MissingVideoStream "No video stream found.\n"
+#define MSGTR_MissingAudioStream "No audio stream found -> no sound.\n"
+#define MSGTR_MissingVideoStreamBug "Missing video stream!? Contact the author, it may be a bug :(\n"
+
+#define MSGTR_DoesntContainSelectedStream "demux: File doesn't contain the selected audio or video stream.\n"
+
+#define MSGTR_NI_Forced "Forced"
+#define MSGTR_NI_Detected "Detected"
+#define MSGTR_NI_Message "%s NON-INTERLEAVED AVI file format.\n"
+
+#define MSGTR_UsingNINI "Using NON-INTERLEAVED broken AVI file format.\n"
+#define MSGTR_CouldntDetFNo "Could not determine number of frames (for absolute seek).\n"
+#define MSGTR_CantSeekRawAVI "Cannot seek in raw AVI streams. (Index required, try with the -idx switch.)\n"
+#define MSGTR_CantSeekFile "Cannot seek in this file.\n"
+
+#define MSGTR_MOVcomprhdr "MOV: Compressed headers support requires ZLIB!\n"
+#define MSGTR_MOVvariableFourCC "MOV: WARNING: Variable FourCC detected!?\n"
+#define MSGTR_MOVtooManyTrk "MOV: WARNING: too many tracks"
+#define MSGTR_FoundAudioStream "==> Found audio stream: %d\n"
+#define MSGTR_FoundVideoStream "==> Found video stream: %d\n"
+#define MSGTR_DetectedTV "TV detected! ;-)\n"
+#define MSGTR_ErrorOpeningOGGDemuxer "Unable to open the Ogg demuxer.\n"
+#define MSGTR_ASFSearchingForAudioStream "ASF: Searching for audio stream (id:%d).\n"
+#define MSGTR_CannotOpenAudioStream "Cannot open audio stream: %s\n"
+#define MSGTR_CannotOpenSubtitlesStream "Cannot open subtitle stream: %s\n"
+#define MSGTR_OpeningAudioDemuxerFailed "Failed to open audio demuxer: %s\n"
+#define MSGTR_OpeningSubtitlesDemuxerFailed "Failed to open subtitle demuxer: %s\n"
+#define MSGTR_TVInputNotSeekable "TV input is not seekable! (Seeking will probably be for changing channels ;)\n"
+#define MSGTR_DemuxerInfoChanged "Demuxer info %s changed to %s\n"
+#define MSGTR_ClipInfo "Clip info:\n"
+
+#define MSGTR_LeaveTelecineMode "\ndemux_mpg: 30000/1001fps NTSC content detected, switching framerate.\n"
+#define MSGTR_EnterTelecineMode "\ndemux_mpg: 24000/1001fps progressive NTSC content detected, switching framerate.\n"
+
+#define MSGTR_CacheFill "\rCache fill: %5.2f%% (%"PRId64" bytes) "
+#define MSGTR_NoBindFound "No bind found for key '%s'."
+#define MSGTR_FailedToOpen "Failed to open %s.\n"
+
+#define MSGTR_VideoID "[%s] Video stream found, -vid %d\n"
+#define MSGTR_AudioID "[%s] Audio stream found, -aid %d\n"
+#define MSGTR_SubtitleID "[%s] Subtitle stream found, -sid %d\n"
+
+// asfheader.c
+#define MSGTR_MPDEMUX_ASFHDR_HeaderSizeOver1MB "FATAL: header size bigger than 1 MB (%d)!\nPlease contact MPlayer authors, and upload/send this file.\n"
+#define MSGTR_MPDEMUX_ASFHDR_HeaderMallocFailed "Could not allocate %d bytes for header.\n"
+#define MSGTR_MPDEMUX_ASFHDR_EOFWhileReadingHeader "EOF while reading ASF header, broken/incomplete file?\n"
+#define MSGTR_MPDEMUX_ASFHDR_DVRWantsLibavformat "DVR will probably only work with libavformat, try -demuxer 35 if you have problems\n"
+#define MSGTR_MPDEMUX_ASFHDR_NoDataChunkAfterHeader "No data chunk following header!\n"
+#define MSGTR_MPDEMUX_ASFHDR_AudioVideoHeaderNotFound "ASF: no audio or video headers found - broken file?\n"
+#define MSGTR_MPDEMUX_ASFHDR_InvalidLengthInASFHeader "Invalid length in ASF header!\n"
+#define MSGTR_MPDEMUX_ASFHDR_DRMLicenseURL "DRM License URL: %s\n"
+#define MSGTR_MPDEMUX_ASFHDR_DRMProtected "This file has been encumbered with DRM encryption, it will not play in MPlayer!\n"
+
+// aviheader.c
+#define MSGTR_MPDEMUX_AVIHDR_EmptyList "** empty list?!\n"
+#define MSGTR_MPDEMUX_AVIHDR_FoundMovieAt "Found movie at 0x%X - 0x%X\n"
+#define MSGTR_MPDEMUX_AVIHDR_FoundBitmapInfoHeader "Found 'bih', %u bytes of %d\n"
+#define MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPG4V1 "Regenerating keyframe table for M$ mpg4v1 video.\n"
+#define MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForDIVX3 "Regenerating keyframe table for DIVX3 video.\n"
+#define MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPEG4 "Regenerating keyframe table for MPEG-4 video.\n"
+#define MSGTR_MPDEMUX_AVIHDR_FoundWaveFmt "Found 'wf', %d bytes of %d\n"
+#define MSGTR_MPDEMUX_AVIHDR_FoundAVIV2Header "AVI: dmlh found (size=%d) (total_frames=%d)\n"
+#define MSGTR_MPDEMUX_AVIHDR_ReadingIndexBlockChunksForFrames "Reading INDEX block, %d chunks for %d frames (fpos=%"PRId64").\n"
+#define MSGTR_MPDEMUX_AVIHDR_AdditionalRIFFHdr "Additional RIFF header...\n"
+#define MSGTR_MPDEMUX_AVIHDR_WarnNotExtendedAVIHdr "** Warning: this is no extended AVI header..\n"
+#define MSGTR_MPDEMUX_AVIHDR_BrokenChunk "Broken chunk? chunksize=%d (id=%.4s)\n"
+#define MSGTR_MPDEMUX_AVIHDR_BuildingODMLidx "AVI: ODML: Building ODML index (%d superindexchunks).\n"
+#define MSGTR_MPDEMUX_AVIHDR_BrokenODMLfile "AVI: ODML: Broken (incomplete?) file detected. Will use traditional index.\n"
+#define MSGTR_MPDEMUX_AVIHDR_CantReadIdxFile "Can't read index file %s: %s\n"
+#define MSGTR_MPDEMUX_AVIHDR_NotValidMPidxFile "%s is not a valid MPlayer index file.\n"
+#define MSGTR_MPDEMUX_AVIHDR_FailedMallocForIdxFile "Could not allocate memory for index data from %s.\n"
+#define MSGTR_MPDEMUX_AVIHDR_PrematureEOF "premature end of index file %s\n"
+#define MSGTR_MPDEMUX_AVIHDR_IdxFileLoaded "Loaded index file: %s\n"
+#define MSGTR_MPDEMUX_AVIHDR_GeneratingIdx "Generating Index: %3lu %s \r"
+#define MSGTR_MPDEMUX_AVIHDR_IdxGeneratedForHowManyChunks "AVI: Generated index table for %d chunks!\n"
+#define MSGTR_MPDEMUX_AVIHDR_Failed2WriteIdxFile "Couldn't write index file %s: %s\n"
+#define MSGTR_MPDEMUX_AVIHDR_IdxFileSaved "Saved index file: %s\n"
+
+// demux_audio.c
+#define MSGTR_MPDEMUX_AUDIO_UnknownFormat "Audio demuxer: unknown format %d.\n"
+
+// demux_demuxers.c
+#define MSGTR_MPDEMUX_DEMUXERS_FillBufferError "fill_buffer error: bad demuxer: not vd, ad or sd.\n"
+
+// demux_mkv.c
+#define MSGTR_MPDEMUX_MKV_ZlibInitializationFailed "[mkv] zlib initialization failed.\n"
+#define MSGTR_MPDEMUX_MKV_ZlibDecompressionFailed "[mkv] zlib decompression failed.\n"
+#define MSGTR_MPDEMUX_MKV_LzoInitializationFailed "[mkv] lzo initialization failed.\n"
+#define MSGTR_MPDEMUX_MKV_LzoDecompressionFailed "[mkv] lzo decompression failed.\n"
+#define MSGTR_MPDEMUX_MKV_TrackEncrypted "[mkv] Track number %u has been encrypted and decryption has not yet been\n[mkv] implemented. Skipping track.\n"
+#define MSGTR_MPDEMUX_MKV_UnknownContentEncoding "[mkv] Unknown content encoding type for track %u. Skipping track.\n"
+#define MSGTR_MPDEMUX_MKV_UnknownCompression "[mkv] Track %u has been compressed with an unknown/unsupported compression\n[mkv] algorithm (%u). Skipping track.\n"
+#define MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported "[mkv] Track %u was compressed with zlib but mplayer has not been compiled\n[mkv] with support for zlib compression. Skipping track.\n"
+#define MSGTR_MPDEMUX_MKV_TrackIDName "[mkv] Track ID %u: %s (%s) \"%s\", %s\n"
+#define MSGTR_MPDEMUX_MKV_TrackID "[mkv] Track ID %u: %s (%s), %s\n"
+#define MSGTR_MPDEMUX_MKV_UnknownCodecID "[mkv] Unknown/unsupported CodecID (%s) or missing/bad CodecPrivate\n[mkv] data (track %u).\n"
+#define MSGTR_MPDEMUX_MKV_FlacTrackDoesNotContainValidHeaders "[mkv] FLAC track does not contain valid headers.\n"
+#define MSGTR_MPDEMUX_MKV_UnknownAudioCodec "[mkv] Unknown/unsupported audio codec ID '%s' for track %u or missing/faulty\n[mkv] private codec data.\n"
+#define MSGTR_MPDEMUX_MKV_SubtitleTypeNotSupported "[mkv] Subtitle type '%s' is not supported.\n"
+#define MSGTR_MPDEMUX_MKV_WillPlayVideoTrack "[mkv] Will play video track %u.\n"
+#define MSGTR_MPDEMUX_MKV_NoVideoTrackFound "[mkv] No video track found/wanted.\n"
+#define MSGTR_MPDEMUX_MKV_NoAudioTrackFound "[mkv] No audio track found/wanted.\n"
+#define MSGTR_MPDEMUX_MKV_WillDisplaySubtitleTrack "[mkv] Will display subtitle track %u.\n"
+#define MSGTR_MPDEMUX_MKV_NoBlockDurationForSubtitleTrackFound "[mkv] Warning: No BlockDuration for subtitle track found.\n"
+#define MSGTR_MPDEMUX_MKV_TooManySublines "[mkv] Warning: too many sublines to render, skipping.\n"
+#define MSGTR_MPDEMUX_MKV_TooManySublinesSkippingAfterFirst "\n[mkv] Warning: too many sublines to render, skipping after first %i.\n"
+
+// demux_nuv.c
+#define MSGTR_MPDEMUX_NUV_NoVideoBlocksInFile "No video blocks in file.\n"
+
+// demux_xmms.c
+#define MSGTR_MPDEMUX_XMMS_FoundPlugin "Found plugin: %s (%s).\n"
+#define MSGTR_MPDEMUX_XMMS_ClosingPlugin "Closing plugin: %s.\n"
+#define MSGTR_MPDEMUX_XMMS_WaitForStart "Waiting for the XMMS plugin to start playback of '%s'...\n"
+
+
+// ========================== LIBMENU ===================================
+
+// common
+#define MSGTR_LIBMENU_NoEntryFoundInTheMenuDefinition "[MENU] No entry found in the menu definition.\n"
+
+// libmenu/menu.c
+#define MSGTR_LIBMENU_SyntaxErrorAtLine "[MENU] syntax error at line: %d\n"
+#define MSGTR_LIBMENU_MenuDefinitionsNeedANameAttrib "[MENU] Menu definitions need a name attribute (line %d).\n"
+#define MSGTR_LIBMENU_BadAttrib "[MENU] bad attribute %s=%s in menu '%s' at line %d\n"
+#define MSGTR_LIBMENU_UnknownMenuType "[MENU] unknown menu type '%s' at line %d\n"
+#define MSGTR_LIBMENU_CantOpenConfigFile "[MENU] Can't open menu config file: %s\n"
+#define MSGTR_LIBMENU_ConfigFileIsTooBig "[MENU] Config file is too big (> %d KB)\n"
+#define MSGTR_LIBMENU_ConfigFileIsEmpty "[MENU] Config file is empty.\n"
+#define MSGTR_LIBMENU_MenuNotFound "[MENU] Menu %s not found.\n"
+#define MSGTR_LIBMENU_MenuInitFailed "[MENU] Menu '%s': Init failed.\n"
+#define MSGTR_LIBMENU_UnsupportedOutformat "[MENU] Unsupported output format!!!!\n"
+
+// libmenu/menu_cmdlist.c
+#define MSGTR_LIBMENU_ListMenuEntryDefinitionsNeedAName "[MENU] List menu entry definitions need a name (line %d).\n"
+#define MSGTR_LIBMENU_ListMenuNeedsAnArgument "[MENU] List menu needs an argument.\n"
+
+// libmenu/menu_console.c
+#define MSGTR_LIBMENU_WaitPidError "[MENU] Waitpid error: %s.\n"
+#define MSGTR_LIBMENU_SelectError "[MENU] Select error.\n"
+#define MSGTR_LIBMENU_ReadErrorOnChildFD "[MENU] Read error on child's file descriptor: %s.\n"
+#define MSGTR_LIBMENU_ConsoleRun "[MENU] Console run: %s ...\n"
+#define MSGTR_LIBMENU_AChildIsAlreadyRunning "[MENU] A child is already running.\n"
+#define MSGTR_LIBMENU_ForkFailed "[MENU] Fork failed !!!\n"
+#define MSGTR_LIBMENU_WriteError "[MENU] write error\n"
+
+// libmenu/menu_filesel.c
+#define MSGTR_LIBMENU_OpendirError "[MENU] opendir error: %s\n"
+#define MSGTR_LIBMENU_ReallocError "[MENU] realloc error: %s\n"
+#define MSGTR_LIBMENU_MallocError "[MENU] memory allocation error: %s\n"
+#define MSGTR_LIBMENU_ReaddirError "[MENU] readdir error: %s\n"
+#define MSGTR_LIBMENU_CantOpenDirectory "[MENU] Can't open directory %s.\n"
+
+// libmenu/menu_param.c
+#define MSGTR_LIBMENU_SubmenuDefinitionNeedAMenuAttribut "[MENU] Submenu definition needs a 'menu' attribute.\n"
+#define MSGTR_LIBMENU_InvalidProperty "[MENU] Invalid property '%s' in pref menu entry. (line %d).\n"
+#define MSGTR_LIBMENU_PrefMenuEntryDefinitionsNeed "[MENU] Pref menu entry definitions need a valid 'property' or 'txt' attribute (line %d).\n"
+#define MSGTR_LIBMENU_PrefMenuNeedsAnArgument "[MENU] Pref menu needs an argument.\n"
+
+// libmenu/menu_pt.c
+#define MSGTR_LIBMENU_CantfindTheTargetItem "[MENU] Can't find the target item ????\n"
+#define MSGTR_LIBMENU_FailedToBuildCommand "[MENU] Failed to build command: %s.\n"
+
+// libmenu/menu_txt.c
+#define MSGTR_LIBMENU_MenuTxtNeedATxtFileName "[MENU] Text menu needs a textfile name (parameter file).\n"
+#define MSGTR_LIBMENU_MenuTxtCantOpen "[MENU] Can't open %s.\n"
+#define MSGTR_LIBMENU_WarningTooLongLineSplitting "[MENU] Warning, line too long. Splitting it.\n"
+#define MSGTR_LIBMENU_ParsedLines "[MENU] Parsed %d lines.\n"
+
+// libmenu/vf_menu.c
+#define MSGTR_LIBMENU_UnknownMenuCommand "[MENU] Unknown command: '%s'.\n"
+#define MSGTR_LIBMENU_FailedToOpenMenu "[MENU] Failed to open menu: '%s'.\n"
+
+
+// ========================== LIBMPCODECS ===================================
+
+// dec_video.c & dec_audio.c:
+#define MSGTR_CantOpenCodec "Could not open codec.\n"
+#define MSGTR_CantCloseCodec "Could not close codec.\n"
+
+#define MSGTR_MissingDLLcodec "ERROR: Could not open required DirectShow codec %s.\n"
+#define MSGTR_ACMiniterror "Could not load/initialize Win32/ACM audio codec (missing DLL file?).\n"
+#define MSGTR_MissingLAVCcodec "Cannot find codec '%s' in libavcodec...\n"
+
+#define MSGTR_MpegNoSequHdr "MPEG: FATAL: EOF while searching for sequence header.\n"
+#define MSGTR_CannotReadMpegSequHdr "FATAL: Cannot read sequence header.\n"
+#define MSGTR_CannotReadMpegSequHdrEx "FATAL: Cannot read sequence header extension.\n"
+#define MSGTR_BadMpegSequHdr "MPEG: bad sequence header\n"
+#define MSGTR_BadMpegSequHdrEx "MPEG: bad sequence header extension\n"
+
+#define MSGTR_ShMemAllocFail "Cannot allocate shared memory.\n"
+#define MSGTR_CantAllocAudioBuf "Cannot allocate audio out buffer.\n"
+
+#define MSGTR_UnknownAudio "Unknown/missing audio format -> no sound\n"
+
+#define MSGTR_UsingExternalPP "[PP] Using external postprocessing filter, max q = %d.\n"
+#define MSGTR_UsingCodecPP "[PP] Using codec's postprocessing, max q = %d.\n"
+#define MSGTR_VideoAttributeNotSupportedByVO_VD "Video attribute '%s' is not supported by selected vo & vd.\n"
+#define MSGTR_VideoCodecFamilyNotAvailableStr "Requested video codec family [%s] (vfm=%s) not available.\nEnable it at compilation.\n"
+#define MSGTR_AudioCodecFamilyNotAvailableStr "Requested audio codec family [%s] (afm=%s) not available.\nEnable it at compilation.\n"
+#define MSGTR_OpeningVideoDecoder "Opening video decoder: [%s] %s\n"
+#define MSGTR_SelectedVideoCodec "Selected video codec: [%s] vfm: %s (%s)\n"
+#define MSGTR_OpeningAudioDecoder "Opening audio decoder: [%s] %s\n"
+#define MSGTR_SelectedAudioCodec "Selected audio codec: [%s] afm: %s (%s)\n"
+#define MSGTR_BuildingAudioFilterChain "Building audio filter chain for %dHz/%dch/%s -> %dHz/%dch/%s...\n"
+#define MSGTR_UninitVideoStr "Uninit video: %s\n"
+#define MSGTR_UninitAudioStr "Uninit audio: %s\n"
+#define MSGTR_VDecoderInitFailed "VDecoder init failed :(\n"
+#define MSGTR_ADecoderInitFailed "ADecoder init failed :(\n"
+#define MSGTR_ADecoderPreinitFailed "ADecoder preinit failed :(\n"
+#define MSGTR_AllocatingBytesForInputBuffer "dec_audio: Allocating %d bytes for input buffer.\n"
+#define MSGTR_AllocatingBytesForOutputBuffer "dec_audio: Allocating %d + %d = %d bytes for output buffer.\n"
+
+// ad_dvdpcm.c:
+#define MSGTR_SamplesWanted "Samples of this format are needed to improve support. Please contact the developers.\n"
+
+// libmpcodecs/ad_libdv.c
+#define MSGTR_MPCODECS_AudioFramesizeDiffers "[AD_LIBDV] Warning! Audio framesize differs! read=%d hdr=%d.\n"
+
+// vd.c
+#define MSGTR_CodecDidNotSet "VDec: Codec did not set sh->disp_w and sh->disp_h, trying workaround.\n"
+#define MSGTR_CouldNotFindColorspace "Could not find matching colorspace - retrying with -vf scale...\n"
+#define MSGTR_MovieAspectIsSet "Movie-Aspect is %.2f:1 - prescaling to correct movie aspect.\n"
+#define MSGTR_MovieAspectUndefined "Movie-Aspect is undefined - no prescaling applied.\n"
+
+// vd_dshow.c, vd_dmo.c
+#define MSGTR_DownloadCodecPackage "You need to upgrade/install the binary codecs package.\nGo to http://www.mplayerhq.hu/dload.html\n"
+#define MSGTR_DShowInitOK "INFO: Win32/DShow video codec init OK.\n"
+#define MSGTR_DMOInitOK "INFO: Win32/DMO video codec init OK.\n"
+
+// libmpcodecs/vd_dmo.c vd_dshow.c vd_vfw.c
+#define MSGTR_MPCODECS_CouldntAllocateImageForCinepakCodec "[VD_DMO] Couldn't allocate image for cinepak codec.\n"
+
+// libmpcodecs/vd_ffmpeg.c
+#define MSGTR_MPCODECS_XVMCAcceleratedCodec "[VD_FFMPEG] XVMC accelerated codec.\n"
+#define MSGTR_MPCODECS_ArithmeticMeanOfQP "[VD_FFMPEG] Arithmetic mean of QP: %2.4f, Harmonic mean of QP: %2.4f\n"
+#define MSGTR_MPCODECS_DRIFailure "[VD_FFMPEG] DRI failure.\n"
+#define MSGTR_MPCODECS_CouldntAllocateImageForCodec "[VD_FFMPEG] Couldn't allocate image for codec.\n"
+#define MSGTR_MPCODECS_XVMCAcceleratedMPEG2 "[VD_FFMPEG] XVMC-accelerated MPEG-2.\n"
+#define MSGTR_MPCODECS_TryingPixfmt "[VD_FFMPEG] Trying pixfmt=%d.\n"
+#define MSGTR_MPCODECS_McGetBufferShouldWorkOnlyWithXVMC "[VD_FFMPEG] The mc_get_buffer should work only with XVMC acceleration!!"
+#define MSGTR_MPCODECS_UnexpectedInitVoError "[VD_FFMPEG] Unexpected init_vo error.\n"
+#define MSGTR_MPCODECS_UnrecoverableErrorRenderBuffersNotTaken "[VD_FFMPEG] Unrecoverable error, render buffers not taken.\n"
+#define MSGTR_MPCODECS_OnlyBuffersAllocatedByVoXvmcAllowed "[VD_FFMPEG] Only buffers allocated by vo_xvmc allowed.\n"
+
+// libmpcodecs/ve_lavc.c
+#define MSGTR_MPCODECS_HighQualityEncodingSelected "[VE_LAVC] High quality encoding selected (non-realtime)!\n"
+#define MSGTR_MPCODECS_UsingConstantQscale "[VE_LAVC] Using constant qscale = %f (VBR).\n"
+
+// libmpcodecs/ve_raw.c
+#define MSGTR_MPCODECS_OutputWithFourccNotSupported "[VE_RAW] Raw output with FourCC [%x] not supported!\n"
+#define MSGTR_MPCODECS_NoVfwCodecSpecified "[VE_RAW] Required VfW codec not specified!!\n"
+
+// vf.c
+#define MSGTR_CouldNotFindVideoFilter "Couldn't find video filter '%s'.\n"
+#define MSGTR_CouldNotOpenVideoFilter "Couldn't open video filter '%s'.\n"
+#define MSGTR_OpeningVideoFilter "Opening video filter: "
+#define MSGTR_CannotFindColorspace "Cannot find matching colorspace, even by inserting 'scale' :(\n"
+
+// libmpcodecs/vf_crop.c
+#define MSGTR_MPCODECS_CropBadPositionWidthHeight "[CROP] Bad position/width/height - cropped area outside of the original!\n"
+
+// libmpcodecs/vf_cropdetect.c
+#define MSGTR_MPCODECS_CropArea "[CROP] Crop area: X: %d..%d Y: %d..%d (-vf crop=%d:%d:%d:%d).\n"
+
+// libmpcodecs/vf_format.c, vf_palette.c, vf_noformat.c
+#define MSGTR_MPCODECS_UnknownFormatName "[VF_FORMAT] Unknown format name: '%s'.\n"
+
+// libmpcodecs/vf_framestep.c vf_noformat.c vf_palette.c vf_tile.c
+#define MSGTR_MPCODECS_ErrorParsingArgument "[VF_FRAMESTEP] Error parsing argument.\n"
+
+// libmpcodecs/ve_vfw.c
+#define MSGTR_MPCODECS_CompressorType "Compressor type: %.4lx\n"
+#define MSGTR_MPCODECS_CompressorSubtype "Compressor subtype: %.4lx\n"
+#define MSGTR_MPCODECS_CompressorFlags "Compressor flags: %lu, version %lu, ICM version: %lu\n"
+#define MSGTR_MPCODECS_Flags "Flags:"
+#define MSGTR_MPCODECS_Quality " quality"
+
+// libmpcodecs/vf_expand.c
+#define MSGTR_MPCODECS_FullDRNotPossible "Full DR not possible, trying SLICES instead!\n"
+#define MSGTR_MPCODECS_WarnNextFilterDoesntSupportSlices "WARNING! Next filter doesn't support SLICES, get ready for sig11...\n"
+#define MSGTR_MPCODECS_FunWhydowegetNULL "Why do we get NULL??\n"
+
+// libmpcodecs/vf_test.c, vf_yuy2.c, vf_yvu9.c
+#define MSGTR_MPCODECS_WarnNextFilterDoesntSupport "%s not supported by next filter/vo :(\n"
+
+
+// ================================== LIBASS ====================================
+
+// ass_bitmap.c
+#define MSGTR_LIBASS_FT_Glyph_To_BitmapError "[ass] FT_Glyph_To_Bitmap error %d \n"
+#define MSGTR_LIBASS_UnsupportedPixelMode "[ass] Unsupported pixel mode: %d\n"
+#define MSGTR_LIBASS_GlyphBBoxTooLarge "[ass] Glyph bounding box too large: %dx%dpx\n"
+
+// ass.c
+#define MSGTR_LIBASS_NoStyleNamedXFoundUsingY "[ass] [%p] Warning: no style named '%s' found, using '%s'\n"
+#define MSGTR_LIBASS_BadTimestamp "[ass] bad timestamp\n"
+#define MSGTR_LIBASS_BadEncodedDataSize "[ass] bad encoded data size\n"
+#define MSGTR_LIBASS_FontLineTooLong "[ass] Font line too long: %d, %s\n"
+#define MSGTR_LIBASS_EventFormatHeaderMissing "[ass] Event format header missing\n"
+#define MSGTR_LIBASS_ErrorOpeningIconvDescriptor "[ass] error opening iconv descriptor.\n"
+#define MSGTR_LIBASS_ErrorRecodingFile "[ass] error recoding file.\n"
+#define MSGTR_LIBASS_FopenFailed "[ass] ass_read_file(%s): fopen failed\n"
+#define MSGTR_LIBASS_FseekFailed "[ass] ass_read_file(%s): fseek failed\n"
+#define MSGTR_LIBASS_RefusingToLoadSubtitlesLargerThan100M "[ass] ass_read_file(%s): Refusing to load subtitles larger than 100M\n"
+#define MSGTR_LIBASS_ReadFailed "Read failed, %d: %s\n"
+#define MSGTR_LIBASS_AddedSubtitleFileMemory "[ass] Added subtitle file: <memory> (%d styles, %d events)\n"
+#define MSGTR_LIBASS_AddedSubtitleFileFname "[ass] Added subtitle file: %s (%d styles, %d events)\n"
+#define MSGTR_LIBASS_FailedToCreateDirectory "[ass] Failed to create directory %s\n"
+#define MSGTR_LIBASS_NotADirectory "[ass] Not a directory: %s\n"
+
+// ass_cache.c
+#define MSGTR_LIBASS_TooManyFonts "[ass] Too many fonts\n"
+#define MSGTR_LIBASS_ErrorOpeningFont "[ass] Error opening font: %s, %d\n"
+
+// ass_fontconfig.c
+#define MSGTR_LIBASS_SelectedFontFamilyIsNotTheRequestedOne "[ass] fontconfig: Selected font is not the requested one: '%s' != '%s'\n"
+#define MSGTR_LIBASS_UsingDefaultFontFamily "[ass] fontconfig_select: Using default font family: (%s, %d, %d) -> %s, %d\n"
+#define MSGTR_LIBASS_UsingDefaultFont "[ass] fontconfig_select: Using default font: (%s, %d, %d) -> %s, %d\n"
+#define MSGTR_LIBASS_UsingArialFontFamily "[ass] fontconfig_select: Using 'Arial' font family: (%s, %d, %d) -> %s, %d\n"
+#define MSGTR_LIBASS_FcInitLoadConfigAndFontsFailed "[ass] FcInitLoadConfigAndFonts failed.\n"
+#define MSGTR_LIBASS_UpdatingFontCache "[ass] Updating font cache.\n"
+#define MSGTR_LIBASS_BetaVersionsOfFontconfigAreNotSupported "[ass] Beta versions of fontconfig are not supported.\n[ass] Update before reporting any bugs.\n"
+#define MSGTR_LIBASS_FcStrSetAddFailed "[ass] FcStrSetAdd failed.\n"
+#define MSGTR_LIBASS_FcDirScanFailed "[ass] FcDirScan failed.\n"
+#define MSGTR_LIBASS_FcDirSave "[ass] FcDirSave failed.\n"
+#define MSGTR_LIBASS_FcConfigAppFontAddDirFailed "[ass] FcConfigAppFontAddDir failed\n"
+#define MSGTR_LIBASS_FontconfigDisabledDefaultFontWillBeUsed "[ass] Fontconfig disabled, only default font will be used.\n"
+#define MSGTR_LIBASS_FunctionCallFailed "[ass] %s failed\n"
+
+// ass_render.c
+#define MSGTR_LIBASS_NeitherPlayResXNorPlayResYDefined "[ass] Neither PlayResX nor PlayResY defined. Assuming 384x288.\n"
+#define MSGTR_LIBASS_PlayResYUndefinedSettingY "[ass] PlayResY undefined, setting %d.\n"
+#define MSGTR_LIBASS_PlayResXUndefinedSettingX "[ass] PlayResX undefined, setting %d.\n"
+#define MSGTR_LIBASS_FT_Init_FreeTypeFailed "[ass] FT_Init_FreeType failed.\n"
+#define MSGTR_LIBASS_Init "[ass] Init\n"
+#define MSGTR_LIBASS_InitFailed "[ass] Init failed.\n"
+#define MSGTR_LIBASS_BadCommand "[ass] Bad command: %c%c\n"
+#define MSGTR_LIBASS_ErrorLoadingGlyph "[ass] Error loading glyph.\n"
+#define MSGTR_LIBASS_FT_Glyph_Stroke_Error "[ass] FT_Glyph_Stroke error %d \n"
+#define MSGTR_LIBASS_UnknownEffectType_InternalError "[ass] Unknown effect type (internal error)\n"
+#define MSGTR_LIBASS_NoStyleFound "[ass] No style found!\n"
+#define MSGTR_LIBASS_EmptyEvent "[ass] Empty event!\n"
+#define MSGTR_LIBASS_MAX_GLYPHS_Reached "[ass] MAX_GLYPHS reached: event %d, start = %llu, duration = %llu\n Text = %s\n"
+#define MSGTR_LIBASS_EventHeightHasChanged "[ass] Warning! Event height has changed! \n"
+
+// ass_font.c
+#define MSGTR_LIBASS_GlyphNotFoundReselectingFont "[ass] Glyph 0x%X not found, selecting one more font for (%s, %d, %d)\n"
+#define MSGTR_LIBASS_GlyphNotFound "[ass] Glyph 0x%X not found in font for (%s, %d, %d)\n"
+#define MSGTR_LIBASS_ErrorOpeningMemoryFont "[ass] Error opening memory font: %s\n"
+#define MSGTR_LIBASS_NoCharmaps "[ass] font face with no charmaps\n"
+#define MSGTR_LIBASS_NoCharmapAutodetected "[ass] no charmap autodetected, trying the first one\n"
+
+
+// ================================== stream ====================================
+
+// ai_alsa1x.c
+#define MSGTR_MPDEMUX_AIALSA1X_CannotSetSamplerate "Cannot set samplerate.\n"
+#define MSGTR_MPDEMUX_AIALSA1X_CannotSetBufferTime "Cannot set buffer time.\n"
+#define MSGTR_MPDEMUX_AIALSA1X_CannotSetPeriodTime "Cannot set period time.\n"
+
+// ai_alsa1x.c / ai_alsa.c
+#define MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig "Broken configuration for this PCM: no configurations available.\n"
+#define MSGTR_MPDEMUX_AIALSA_UnavailableAccessType "Access type not available.\n"
+#define MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt "Sample format not available.\n"
+#define MSGTR_MPDEMUX_AIALSA_UnavailableChanCount "Channel count not available - reverting to default: %d\n"
+#define MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams "Unable to install hardware parameters: %s"
+#define MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize "Can't use period equal to buffer size (%u == %lu)\n"
+#define MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams "Unable to install software parameters:\n"
+#define MSGTR_MPDEMUX_AIALSA_ErrorOpeningAudio "Error opening audio: %s\n"
+#define MSGTR_MPDEMUX_AIALSA_AlsaStatusError "ALSA status error: %s"
+#define MSGTR_MPDEMUX_AIALSA_AlsaXRUN "ALSA xrun!!! (at least %.3f ms long)\n"
+#define MSGTR_MPDEMUX_AIALSA_AlsaStatus "ALSA Status:\n"
+#define MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError "ALSA xrun: prepare error: %s"
+#define MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError "ALSA read/write error"
+
+// ai_oss.c
+#define MSGTR_MPDEMUX_AIOSS_Unable2SetChanCount "Unable to set channel count: %d\n"
+#define MSGTR_MPDEMUX_AIOSS_Unable2SetStereo "Unable to set stereo: %d\n"
+#define MSGTR_MPDEMUX_AIOSS_Unable2Open "Unable to open '%s': %s\n"
+#define MSGTR_MPDEMUX_AIOSS_UnsupportedFmt "unsupported format\n"
+#define MSGTR_MPDEMUX_AIOSS_Unable2SetAudioFmt "Unable to set audio format."
+#define MSGTR_MPDEMUX_AIOSS_Unable2SetSamplerate "Unable to set samplerate: %d\n"
+#define MSGTR_MPDEMUX_AIOSS_Unable2SetTrigger "Unable to set trigger: %d\n"
+#define MSGTR_MPDEMUX_AIOSS_Unable2GetBlockSize "Unable to get block size!\n"
+#define MSGTR_MPDEMUX_AIOSS_AudioBlockSizeZero "Audio block size is zero, setting to %d!\n"
+#define MSGTR_MPDEMUX_AIOSS_AudioBlockSize2Low "Audio block size too low, setting to %d!\n"
+
+// asf_mmst_streaming.c
+#define MSGTR_MPDEMUX_MMST_WriteError "write error\n"
+#define MSGTR_MPDEMUX_MMST_EOFAlert "\nAlert! EOF\n"
+#define MSGTR_MPDEMUX_MMST_PreHeaderReadFailed "pre-header read failed\n"
+#define MSGTR_MPDEMUX_MMST_InvalidHeaderSize "Invalid header size, giving up.\n"
+#define MSGTR_MPDEMUX_MMST_HeaderDataReadFailed "Header data read failed.\n"
+#define MSGTR_MPDEMUX_MMST_packet_lenReadFailed "packet_len read failed.\n"
+#define MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize "Invalid RTSP packet size, giving up.\n"
+#define MSGTR_MPDEMUX_MMST_CmdDataReadFailed "Command data read failed.\n"
+#define MSGTR_MPDEMUX_MMST_HeaderObject "header object\n"
+#define MSGTR_MPDEMUX_MMST_DataObject "data object\n"
+#define MSGTR_MPDEMUX_MMST_FileObjectPacketLen "file object, packet length = %d (%d)\n"
+#define MSGTR_MPDEMUX_MMST_StreamObjectStreamID "stream object, stream ID: %d\n"
+#define MSGTR_MPDEMUX_MMST_2ManyStreamID "Too many IDs, stream skipped."
+#define MSGTR_MPDEMUX_MMST_UnknownObject "unknown object\n"
+#define MSGTR_MPDEMUX_MMST_MediaDataReadFailed "Media data read failed.\n"
+#define MSGTR_MPDEMUX_MMST_MissingSignature "missing signature\n"
+#define MSGTR_MPDEMUX_MMST_PatentedTechnologyJoke "Everything done. Thank you for downloading a media file containing proprietary and patented technology.\n"
+#define MSGTR_MPDEMUX_MMST_UnknownCmd "unknown command %02x\n"
+#define MSGTR_MPDEMUX_MMST_GetMediaPacketErr "get_media_packet error : %s\n"
+#define MSGTR_MPDEMUX_MMST_Connected "Connected\n"
+
+// asf_streaming.c
+#define MSGTR_MPDEMUX_ASF_StreamChunkSize2Small "Ahhhh, stream_chunck size is too small: %d\n"
+#define MSGTR_MPDEMUX_ASF_SizeConfirmMismatch "size_confirm mismatch!: %d %d\n"
+#define MSGTR_MPDEMUX_ASF_WarnDropHeader "Warning: drop header ????\n"
+#define MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader "Error while parsing chunk header\n"
+#define MSGTR_MPDEMUX_ASF_NoHeaderAtFirstChunk "Didn't get a header as first chunk !!!!\n"
+#define MSGTR_MPDEMUX_ASF_BufferMallocFailed "Error: Can't allocate %d bytes buffer.\n"
+#define MSGTR_MPDEMUX_ASF_ErrReadingNetworkStream "Error while reading network stream.\n"
+#define MSGTR_MPDEMUX_ASF_ErrChunk2Small "Error: Chunk is too small.\n"
+#define MSGTR_MPDEMUX_ASF_ErrSubChunkNumberInvalid "Error: Subchunk number is invalid.\n"
+#define MSGTR_MPDEMUX_ASF_Bandwidth2SmallCannotPlay "Bandwidth too small, file cannot be played!\n"
+#define MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedAudio "Bandwidth too small, deselected audio stream.\n"
+#define MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedVideo "Bandwidth too small, deselected video stream.\n"
+#define MSGTR_MPDEMUX_ASF_InvalidLenInHeader "Invalid length in ASF header!\n"
+#define MSGTR_MPDEMUX_ASF_ErrReadingChunkHeader "Error while reading chunk header.\n"
+#define MSGTR_MPDEMUX_ASF_ErrChunkBiggerThanPacket "Error: chunk_size > packet_size\n"
+#define MSGTR_MPDEMUX_ASF_ErrReadingChunk "Error while reading chunk.\n"
+#define MSGTR_MPDEMUX_ASF_ASFRedirector "=====> ASF Redirector\n"
+#define MSGTR_MPDEMUX_ASF_InvalidProxyURL "invalid proxy URL\n"
+#define MSGTR_MPDEMUX_ASF_UnknownASFStreamType "unknown ASF stream type\n"
+#define MSGTR_MPDEMUX_ASF_Failed2ParseHTTPResponse "Failed to parse HTTP response.\n"
+#define MSGTR_MPDEMUX_ASF_ServerReturn "Server returned %d:%s\n"
+#define MSGTR_MPDEMUX_ASF_ASFHTTPParseWarnCuttedPragma "ASF HTTP PARSE WARNING : Pragma %s cut from %zd bytes to %d\n"
+#define MSGTR_MPDEMUX_ASF_SocketWriteError "socket write error: %s\n"
+#define MSGTR_MPDEMUX_ASF_HeaderParseFailed "Failed to parse header.\n"
+#define MSGTR_MPDEMUX_ASF_NoStreamFound "No stream found.\n"
+#define MSGTR_MPDEMUX_ASF_UnknownASFStreamingType "unknown ASF streaming type\n"
+#define MSGTR_MPDEMUX_ASF_InfoStreamASFURL "STREAM_ASF, URL: %s\n"
+#define MSGTR_MPDEMUX_ASF_StreamingFailed "Failed, exiting.\n"
+
+// audio_in.c
+#define MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio "\nError reading audio: %s\n"
+#define MSGTR_MPDEMUX_AUDIOIN_XRUNSomeFramesMayBeLeftOut "Recovered from cross-run, some frames may be left out!\n"
+#define MSGTR_MPDEMUX_AUDIOIN_ErrFatalCannotRecover "Fatal error, cannot recover!\n"
+#define MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples "\nNot enough audio samples!\n"
+
+// cache2.c
+#define MSGTR_MPDEMUX_CACHE2_NonCacheableStream "\rThis stream is non-cacheable.\n"
+#define MSGTR_MPDEMUX_CACHE2_ReadFileposDiffers "!!! read_filepos differs!!! Report this bug...\n"
+
+// network.c
+#define MSGTR_MPDEMUX_NW_UnknownAF "Unknown address family %d\n"
+#define MSGTR_MPDEMUX_NW_ResolvingHostForAF "Resolving %s for %s...\n"
+#define MSGTR_MPDEMUX_NW_CantResolv "Couldn't resolve name for %s: %s\n"
+#define MSGTR_MPDEMUX_NW_ConnectingToServer "Connecting to server %s[%s]: %d...\n"
+#define MSGTR_MPDEMUX_NW_CantConnect2Server "Failed to connect to server with %s\n"
+#define MSGTR_MPDEMUX_NW_SelectFailed "Select failed.\n"
+#define MSGTR_MPDEMUX_NW_ConnTimeout "connection timeout\n"
+#define MSGTR_MPDEMUX_NW_GetSockOptFailed "getsockopt failed: %s\n"
+#define MSGTR_MPDEMUX_NW_ConnectError "connect error: %s\n"
+#define MSGTR_MPDEMUX_NW_InvalidProxySettingTryingWithout "Invalid proxy setting... Trying without proxy.\n"
+#define MSGTR_MPDEMUX_NW_CantResolvTryingWithoutProxy "Could not resolve remote hostname for AF_INET. Trying without proxy.\n"
+#define MSGTR_MPDEMUX_NW_ErrSendingHTTPRequest "Error while sending HTTP request: Didn't send all the request.\n"
+#define MSGTR_MPDEMUX_NW_ReadFailed "Read failed.\n"
+#define MSGTR_MPDEMUX_NW_Read0CouldBeEOF "http_read_response read 0 (i.e. EOF).\n"
+#define MSGTR_MPDEMUX_NW_AuthFailed "Authentication failed. Please use the -user and -passwd options to provide your\n"\
+"username/password for a list of URLs, or form an URL like:\n"\
+"http://username:password@hostname/file\n"
+#define MSGTR_MPDEMUX_NW_AuthRequiredFor "Authentication required for %s\n"
+#define MSGTR_MPDEMUX_NW_AuthRequired "Authentication required.\n"
+#define MSGTR_MPDEMUX_NW_NoPasswdProvidedTryingBlank "No password provided, trying blank password.\n"
+#define MSGTR_MPDEMUX_NW_ErrServerReturned "Server returns %d: %s\n"
+#define MSGTR_MPDEMUX_NW_CacheSizeSetTo "Cache size set to %d KBytes\n"
+
+// open.c, stream.c:
+#define MSGTR_CdDevNotfound "CD-ROM Device '%s' not found.\n"
+#define MSGTR_ErrTrackSelect "Error selecting VCD track."
+#define MSGTR_ReadSTDIN "Reading from stdin...\n"
+#define MSGTR_UnableOpenURL "Unable to open URL: %s\n"
+#define MSGTR_ConnToServer "Connected to server: %s\n"
+#define MSGTR_FileNotFound "File not found: '%s'\n"
+
+#define MSGTR_SMBInitError "Cannot init the libsmbclient library: %d\n"
+#define MSGTR_SMBFileNotFound "Could not open from LAN: '%s'\n"
+#define MSGTR_SMBNotCompiled "MPlayer was not compiled with SMB reading support.\n"
+
+#define MSGTR_CantOpenBluray "Couldn't open Blu-ray device: %s\n"
+#define MSGTR_CantOpenDVD "Couldn't open DVD device: %s (%s)\n"
+
+// stream_cdda.c
+#define MSGTR_MPDEMUX_CDDA_CantOpenCDDADevice "Can't open CDDA device.\n"
+#define MSGTR_MPDEMUX_CDDA_CantOpenDisc "Can't open disc.\n"
+#define MSGTR_MPDEMUX_CDDA_AudioCDFoundWithNTracks "Found audio CD with %d tracks.\n"
+
+// stream_cddb.c
+#define MSGTR_MPDEMUX_CDDB_FailedToReadTOC "Failed to read TOC.\n"
+#define MSGTR_MPDEMUX_CDDB_FailedToOpenDevice "Failed to open %s device.\n"
+#define MSGTR_MPDEMUX_CDDB_NotAValidURL "not a valid URL\n"
+#define MSGTR_MPDEMUX_CDDB_FailedToSendHTTPRequest "Failed to send the HTTP request.\n"
+#define MSGTR_MPDEMUX_CDDB_FailedToReadHTTPResponse "Failed to read the HTTP response.\n"
+#define MSGTR_MPDEMUX_CDDB_HTTPErrorNOTFOUND "Not Found.\n"
+#define MSGTR_MPDEMUX_CDDB_HTTPErrorUnknown "unknown error code\n"
+#define MSGTR_MPDEMUX_CDDB_NoCacheFound "No cache found.\n"
+#define MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenRead "Not all the xmcd file has been read.\n"
+#define MSGTR_MPDEMUX_CDDB_FailedToCreateDirectory "Failed to create directory %s.\n"
+#define MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenWritten "Not all of the xmcd file has been written.\n"
+#define MSGTR_MPDEMUX_CDDB_InvalidXMCDDatabaseReturned "Invalid xmcd database file returned.\n"
+#define MSGTR_MPDEMUX_CDDB_UnexpectedFIXME "unexpected FIXME\n"
+#define MSGTR_MPDEMUX_CDDB_UnhandledCode "unhandled code\n"
+#define MSGTR_MPDEMUX_CDDB_UnableToFindEOL "Unable to find end of line.\n"
+#define MSGTR_MPDEMUX_CDDB_ParseOKFoundAlbumTitle "Parse OK, found: %s\n"
+#define MSGTR_MPDEMUX_CDDB_AlbumNotFound "Album not found.\n"
+#define MSGTR_MPDEMUX_CDDB_ServerReturnsCommandSyntaxErr "Server returns: Command syntax error\n"
+#define MSGTR_MPDEMUX_CDDB_NoSitesInfoAvailable "No sites information available.\n"
+#define MSGTR_MPDEMUX_CDDB_FailedToGetProtocolLevel "Failed to get the protocol level.\n"
+#define MSGTR_MPDEMUX_CDDB_NoCDInDrive "No CD in the drive.\n"
+
+// stream_cue.c
+#define MSGTR_MPDEMUX_CUEREAD_UnexpectedCuefileLine "[bincue] Unexpected cuefile line: %s\n"
+#define MSGTR_MPDEMUX_CUEREAD_BinFilenameTested "[bincue] bin filename tested: %s\n"
+#define MSGTR_MPDEMUX_CUEREAD_CannotFindBinFile "[bincue] Couldn't find the bin file - giving up.\n"
+#define MSGTR_MPDEMUX_CUEREAD_UsingBinFile "[bincue] Using bin file %s.\n"
+#define MSGTR_MPDEMUX_CUEREAD_UnknownModeForBinfile "[bincue] unknown mode for binfile. Should not happen. Aborting.\n"
+#define MSGTR_MPDEMUX_CUEREAD_CannotOpenCueFile "[bincue] Cannot open %s.\n"
+#define MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile "[bincue] Error reading from %s\n"
+#define MSGTR_MPDEMUX_CUEREAD_ErrGettingBinFileSize "[bincue] Error getting size of bin file.\n"
+#define MSGTR_MPDEMUX_CUEREAD_InfoTrackFormat "track %02d: format=%d %02d:%02d:%02d\n"
+#define MSGTR_MPDEMUX_CUEREAD_UnexpectedBinFileEOF "[bincue] unexpected end of bin file\n"
+#define MSGTR_MPDEMUX_CUEREAD_CannotReadNBytesOfPayload "[bincue] Couldn't read %d bytes of payload.\n"
+#define MSGTR_MPDEMUX_CUEREAD_CueStreamInfo_FilenameTrackTracksavail "CUE stream_open, filename=%s, track=%d, available tracks: %d -> %d\n"
+
+// stream_dvd.c
+#define MSGTR_DVDspeedCantOpen "Couldn't open DVD device for writing, changing DVD speed needs write access.\n"
+#define MSGTR_DVDrestoreSpeed "Restoring DVD speed... "
+#define MSGTR_DVDlimitSpeed "Limiting DVD speed to %dKB/s... "
+#define MSGTR_DVDlimitFail "failed\n"
+#define MSGTR_DVDlimitOk "successful\n"
+#define MSGTR_NoDVDSupport "MPlayer was compiled without DVD support, exiting.\n"
+#define MSGTR_DVDnumTitles "There are %d titles on this DVD.\n"
+#define MSGTR_DVDinvalidTitle "Invalid DVD title number: %d\n"
+#define MSGTR_DVDnumChapters "There are %d chapters in this DVD title.\n"
+#define MSGTR_DVDinvalidChapter "Invalid DVD chapter number: %d\n"
+#define MSGTR_DVDinvalidChapterRange "Invalid chapter range specification %s\n"
+#define MSGTR_DVDinvalidLastChapter "Invalid DVD last chapter number: %d\n"
+#define MSGTR_DVDnumAngles "There are %d angles in this DVD title.\n"
+#define MSGTR_DVDinvalidAngle "Invalid DVD angle number: %d\n"
+#define MSGTR_DVDnoIFO "Cannot open the IFO file for DVD title %d.\n"
+#define MSGTR_DVDnoVMG "Can't open VMG info!\n"
+#define MSGTR_DVDnoVOBs "Cannot open title VOBS (VTS_%02d_1.VOB).\n"
+#define MSGTR_DVDnoMatchingAudio "No matching DVD audio language found!\n"
+#define MSGTR_DVDaudioChannel "Selected DVD audio channel: %d language: %c%c\n"
+#define MSGTR_DVDaudioStreamInfo "audio stream: %d format: %s (%s) language: %s aid: %d.\n"
+#define MSGTR_DVDnumAudioChannels "number of audio channels on disk: %d.\n"
+#define MSGTR_DVDnoMatchingSubtitle "No matching DVD subtitle language found!\n"
+#define MSGTR_DVDsubtitleChannel "Selected DVD subtitle channel: %d language: %c%c\n"
+#define MSGTR_DVDsubtitleLanguage "subtitle ( sid ): %d language: %s\n"
+#define MSGTR_DVDnumSubtitles "number of subtitles on disk: %d\n"
+
+// stream_bluray.c
+#define MSGTR_BlurayNoDevice "No Blu-ray device/location was specified ...\n"
+#define MSGTR_BlurayNoTitles "Can't find any Blu-ray-compatible title here.\n"
+#define MSGTR_BlurayOK "Blu-ray successfully opened.\n"
+
+// stream_radio.c
+#define MSGTR_RADIO_ChannelNamesDetected "[radio] Radio channel names detected.\n"
+#define MSGTR_RADIO_FreqRange "[radio] Allowed frequency range is %.2f-%.2f MHz.\n"
+#define MSGTR_RADIO_WrongFreqForChannel "[radio] Wrong frequency for channel %s\n"
+#define MSGTR_RADIO_WrongChannelNumberFloat "[radio] Wrong channel number: %.2f\n"
+#define MSGTR_RADIO_WrongChannelNumberInt "[radio] Wrong channel number: %d\n"
+#define MSGTR_RADIO_WrongChannelName "[radio] Wrong channel name: %s\n"
+#define MSGTR_RADIO_FreqParameterDetected "[radio] Radio frequency parameter detected.\n"
+#define MSGTR_RADIO_DoneParsingChannels "[radio] Done parsing channels.\n"
+#define MSGTR_RADIO_GetTunerFailed "[radio] Warning: ioctl get tuner failed: %s. Setting frac to %d.\n"
+#define MSGTR_RADIO_NotRadioDevice "[radio] %s is no radio device!\n"
+#define MSGTR_RADIO_TunerCapLowYes "[radio] tuner is low:yes frac=%d\n"
+#define MSGTR_RADIO_TunerCapLowNo "[radio] tuner is low:no frac=%d\n"
+#define MSGTR_RADIO_SetFreqFailed "[radio] ioctl set frequency 0x%x (%.2f) failed: %s\n"
+#define MSGTR_RADIO_GetFreqFailed "[radio] ioctl get frequency failed: %s\n"
+#define MSGTR_RADIO_SetMuteFailed "[radio] ioctl set mute failed: %s\n"
+#define MSGTR_RADIO_QueryControlFailed "[radio] ioctl query control failed: %s\n"
+#define MSGTR_RADIO_GetVolumeFailed "[radio] ioctl get volume failed: %s\n"
+#define MSGTR_RADIO_SetVolumeFailed "[radio] ioctl set volume failed: %s\n"
+#define MSGTR_RADIO_DroppingFrame "\n[radio] too bad - dropping audio frame (%d bytes)!\n"
+#define MSGTR_RADIO_BufferEmpty "[radio] grab_audio_frame: buffer empty, waiting for %d data bytes.\n"
+#define MSGTR_RADIO_AudioInitFailed "[radio] audio_in_init failed: %s\n"
+#define MSGTR_RADIO_AudioBuffer "[radio] Audio capture - buffer=%d bytes (block=%d bytes).\n"
+#define MSGTR_RADIO_AllocateBufferFailed "[radio] cannot allocate audio buffer (block=%d,buf=%d): %s\n"
+#define MSGTR_RADIO_CurrentFreq "[radio] Current frequency: %.2f\n"
+#define MSGTR_RADIO_SelectedChannel "[radio] Selected channel: %d - %s (freq: %.2f)\n"
+#define MSGTR_RADIO_ChangeChannelNoChannelList "[radio] Can not change channel: no channel list given.\n"
+#define MSGTR_RADIO_UnableOpenDevice "[radio] Unable to open '%s': %s\n"
+#define MSGTR_RADIO_RadioDevice "[radio] Radio fd: %d, %s\n"
+#define MSGTR_RADIO_InitFracFailed "[radio] init_frac failed.\n"
+#define MSGTR_RADIO_WrongFreq "[radio] Wrong frequency: %.2f\n"
+#define MSGTR_RADIO_UsingFreq "[radio] Using frequency: %.2f.\n"
+#define MSGTR_RADIO_AudioInInitFailed "[radio] audio_in_init failed.\n"
+#define MSGTR_RADIO_BufferString "[radio] %s: in buffer=%d dropped=%d\n"
+#define MSGTR_RADIO_AudioInSetupFailed "[radio] audio_in_setup call failed: %s\n"
+#define MSGTR_RADIO_CaptureStarting "[radio] Starting capture stuff.\n"
+#define MSGTR_RADIO_ClearBufferFailed "[radio] Clearing buffer failed: %s\n"
+#define MSGTR_RADIO_StreamEnableCacheFailed "[radio] Call to stream_enable_cache failed: %s\n"
+#define MSGTR_RADIO_DriverUnknownStr "[radio] Unknown driver name: %s\n"
+#define MSGTR_RADIO_DriverV4L2 "[radio] Using V4Lv2 radio interface.\n"
+#define MSGTR_RADIO_DriverV4L "[radio] Using V4Lv1 radio interface.\n"
+#define MSGTR_RADIO_DriverBSDBT848 "[radio] Using *BSD BT848 radio interface.\n"
+#define MSGTR_RADIO_AvailableDrivers "[radio] Available drivers: "
+
+//tv.c
+#define MSGTR_TV_BogusNormParameter "tv.c: norm_from_string(%s): Bogus norm parameter, setting %s.\n"
+#define MSGTR_TV_NoVideoInputPresent "Error: No video input present!\n"
+#define MSGTR_TV_UnknownImageFormat ""\
+"==================================================================\n"\
+" WARNING: UNTESTED OR UNKNOWN OUTPUT IMAGE FORMAT REQUESTED (0x%x)\n"\
+" This may cause buggy playback or program crash! Bug reports will\n"\
+" be ignored! You should try again with YV12 (which is the default\n"\
+" colorspace) and read the documentation!\n"\
+"==================================================================\n"
+#define MSGTR_TV_SelectedNormId "Selected norm id: %d\n"
+#define MSGTR_TV_SelectedNorm "Selected norm : %s\n"
+#define MSGTR_TV_CannotSetNorm "Error: Cannot set norm!\n"
+#define MSGTR_TV_MJP_WidthHeight " MJP: width %d height %d\n"
+#define MSGTR_TV_UnableToSetWidth "Unable to set requested width: %d\n"
+#define MSGTR_TV_UnableToSetHeight "Unable to set requested height: %d\n"
+#define MSGTR_TV_NoTuner "Selected input hasn't got a tuner!\n"
+#define MSGTR_TV_UnableFindChanlist "Unable to find selected channel list! (%s)\n"
+#define MSGTR_TV_SelectedChanlist "Selected channel list: %s (including %d channels)\n"
+#define MSGTR_TV_ChannelFreqParamConflict "You can't set frequency and channel simultaneously!\n"
+#define MSGTR_TV_ChannelNamesDetected "TV channel names detected.\n"
+#define MSGTR_TV_NoFreqForChannel "Couldn't find frequency for channel %s (%s)\n"
+#define MSGTR_TV_SelectedChannel3 "Selected channel: %s - %s (freq: %.3f)\n"
+#define MSGTR_TV_SelectedChannel2 "Selected channel: %s (freq: %.3f)\n"
+#define MSGTR_TV_SelectedFrequency "Selected frequency: %lu (%.3f)\n"
+#define MSGTR_TV_RequestedChannel "Requested channel: %s\n"
+#define MSGTR_TV_UnsupportedAudioType "Audio type '%s (%x)' unsupported!\n"
+#define MSGTR_TV_AudioFormat " TV audio: %d channels, %d bits, %d Hz\n"
+#define MSGTR_TV_AvailableDrivers "Available drivers:\n"
+#define MSGTR_TV_DriverInfo "Selected driver: %s\n name: %s\n author: %s\n comment: %s\n"
+#define MSGTR_TV_NoSuchDriver "No such driver: %s\n"
+#define MSGTR_TV_DriverAutoDetectionFailed "TV driver autodetection failed.\n"
+#define MSGTR_TV_UnknownColorOption "Unknown color option (%d) specified!\n"
+#define MSGTR_TV_CurrentFrequency "Current frequency: %lu (%.3f)\n"
+#define MSGTR_TV_NoTeletext "No teletext"
+#define MSGTR_TV_Bt848IoctlFailed "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n"
+#define MSGTR_TV_Bt848InvalidAudioRate "tvi_bsdbt848: Invalid audio rate. Error: %s\n"
+#define MSGTR_TV_Bt848ErrorOpeningBktrDev "tvi_bsdbt848: Unable to open bktr device. Error: %s\n"
+#define MSGTR_TV_Bt848ErrorOpeningTunerDev "tvi_bsdbt848: Unable to open tuner device. Error: %s\n"
+#define MSGTR_TV_Bt848ErrorOpeningDspDev "tvi_bsdbt848: Unable to open dsp device. Error: %s\n"
+#define MSGTR_TV_Bt848ErrorConfiguringDsp "tvi_bsdbt848: Configuration of dsp failed. Error: %s\n"
+#define MSGTR_TV_Bt848ErrorReadingAudio "tvi_bsdbt848: Error reading audio data. Error: %s\n"
+#define MSGTR_TV_Bt848MmapFailed "tvi_bsdbt848: mmap failed. Error: %s\n"
+#define MSGTR_TV_Bt848FrameBufAllocFailed "tvi_bsdbt848: Frame buffer allocation failed. Error: %s\n"
+#define MSGTR_TV_Bt848ErrorSettingWidth "tvi_bsdbt848: Error setting picture width. Error: %s\n"
+#define MSGTR_TV_Bt848ErrorSettingHeight "tvi_bsdbt848: Error setting picture height. Error: %s\n"
+#define MSGTR_TV_Bt848UnableToStopCapture "tvi_bsdbt848: Unable to stop capture. Error: %s\n"
+#define MSGTR_TV_TTSupportedLanguages "Supported Teletext languages:\n"
+#define MSGTR_TV_TTSelectedLanguage "Selected default teletext language: %s\n"
+#define MSGTR_TV_ScannerNotAvailableWithoutTuner "Channel scanner is not available without tuner\n"
+
+//tvi_dshow.c
+#define MSGTR_TVI_DS_UnableConnectInputVideoDecoder "Unable to connect given input to video decoder. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableConnectInputAudioDecoder "Unable to connect given input to audio decoder. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableSelectVideoFormat "tvi_dshow: Unable to select video format. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableSelectAudioFormat "tvi_dshow: Unable to select audio format. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableGetMediaControlInterface "tvi_dshow: Unable to get IMediaControl interface. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableStartGraph "tvi_dshow: Unable to start graph! Error:0x%x\n"
+#define MSGTR_TVI_DS_DeviceNotFound "tvi_dshow: Device #%d not found\n"
+#define MSGTR_TVI_DS_UnableGetDeviceName "tvi_dshow: Unable to get name for device #%d\n"
+#define MSGTR_TVI_DS_UsingDevice "tvi_dshow: Using device #%d: %s\n"
+#define MSGTR_TVI_DS_DeviceName "tvi_dshow: Device #%d: %s\n"
+#define MSGTR_TVI_DS_DirectGetFreqFailed "tvi_dshow: Unable to get frequency directly. OS built-in channels table will be used.\n"
+#define MSGTR_TVI_DS_DirectSetFreqFailed "tvi_dshow: Unable to set frequency directly. OS built-in channels table will be used.\n"
+#define MSGTR_TVI_DS_SupportedNorms "tvi_dshow: supported norms:"
+#define MSGTR_TVI_DS_AvailableVideoInputs "tvi_dshow: available video inputs:"
+#define MSGTR_TVI_DS_AvailableAudioInputs "tvi_dshow: available audio inputs:"
+//following phrase will be printed near the selected audio/video input
+#define MSGTR_TVI_DS_InputSelected "(selected)"
+#define MSGTR_TVI_DS_UnableExtractFreqTable "tvi_dshow: Unable to load frequency table from kstvtune.ax\n"
+#define MSGTR_TVI_DS_WrongDeviceParam "tvi_dshow: Wrong device parameter: %s\n"
+#define MSGTR_TVI_DS_WrongDeviceIndex "tvi_dshow: Wrong device index: %d\n"
+#define MSGTR_TVI_DS_WrongADeviceParam "tvi_dshow: Wrong adevice parameter: %s\n"
+#define MSGTR_TVI_DS_WrongADeviceIndex "tvi_dshow: Wrong adevice index: %d\n"
+
+#define MSGTR_TVI_DS_SamplerateNotsupported "tvi_dshow: Samplerate %d is not supported by device. Failing back to first available.\n"
+#define MSGTR_TVI_DS_VideoAdjustigNotSupported "tvi_dshow: Adjusting of brightness/hue/saturation/contrast is not supported by device\n"
+
+#define MSGTR_TVI_DS_ChangingWidthHeightNotSupported "tvi_dshow: Changing video width/height is not supported by device.\n"
+#define MSGTR_TVI_DS_SelectingInputNotSupported "tvi_dshow: Selection of capture source is not supported by device\n"
+#define MSGTR_TVI_DS_FreqTableLoaded "tvi_dshow: loaded system (%s) frequency table for country id=%d (channels:%d).\n"
+#define MSGTR_TVI_DS_ErrorParsingAudioFormatStruct "tvi_dshow: Unable to parse audio format structure.\n"
+#define MSGTR_TVI_DS_ErrorParsingVideoFormatStruct "tvi_dshow: Unable to parse video format structure.\n"
+#define MSGTR_TVI_DS_UnableSetAudioMode "tvi_dshow: Unable to set audio mode %d. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnsupportedMediaType "tvi_dshow: Unsupported media type passed to %s\n"
+#define MSGTR_TVI_DS_UnableGetsupportedVideoFormats "tvi_dshow: Unable to get supported media formats from video pin. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableGetsupportedAudioFormats "tvi_dshow: Unable to get supported media formats from audio pin. Error:0x%x Disabling audio.\n"
+#define MSGTR_TVI_DS_UnableFindNearestChannel "tvi_dshow: Unable to find nearest channel in system frequency table\n"
+#define MSGTR_TVI_DS_UnableToSetChannel "tvi_dshow: Unable to switch to nearest channel from system frequency table. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableTerminateVPPin "tvi_dshow: Unable to terminate VideoPort pin with any filter in graph. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableBuildVideoSubGraph "tvi_dshow: Unable to build video chain of capture graph. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableBuildAudioSubGraph "tvi_dshow: Unable to build audio chain of capture graph. Error:0x%x\n"
+#define MSGTR_TVI_DS_UnableBuildVBISubGraph "tvi_dshow: Unable to build VBI chain of capture graph. Error:0x%x\n"
+#define MSGTR_TVI_DS_GraphInitFailure "tvi_dshow: Directshow graph initialization failure.\n"
+#define MSGTR_TVI_DS_NoVideoCaptureDevice "tvi_dshow: Unable to find video capture device\n"
+#define MSGTR_TVI_DS_NoAudioCaptureDevice "tvi_dshow: Unable to find audio capture device\n"
+#define MSGTR_TVI_DS_GetActualMediatypeFailed "tvi_dshow: Unable to get actual mediatype (Error:0x%x). Assuming equal to requested.\n"
+
+// url.c
+#define MSGTR_MPDEMUX_URL_StringAlreadyEscaped "String appears to be already escaped in url_escape %c%c1%c2\n"
+
+// subtitles
+#define MSGTR_SUBTITLES_SubRip_UnknownFontColor "SubRip: unknown font color in subtitle: %s\n"
+
+
+/* untranslated messages from the English master file */
+
+
+#endif /* MPLAYER_HELP_MP_H */
diff --git a/libavfilter/libmpcodecs/img_format.c b/libavfilter/libmpcodecs/img_format.c
new file mode 100644
index 0000000000..ba870421d3
--- /dev/null
+++ b/libavfilter/libmpcodecs/img_format.c
@@ -0,0 +1,170 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "img_format.h"
+#include "stdio.h"
+
+const char *vo_format_name(int format)
+{
+ static char unknown_format[20];
+ switch(format)
+ {
+ case IMGFMT_RGB1: return "RGB 1-bit";
+ case IMGFMT_RGB4: return "RGB 4-bit";
+ case IMGFMT_RG4B: return "RGB 4-bit per byte";
+ case IMGFMT_RGB8: return "RGB 8-bit";
+ case IMGFMT_RGB12: return "RGB 12-bit";
+ case IMGFMT_RGB15: return "RGB 15-bit";
+ case IMGFMT_RGB16: return "RGB 16-bit";
+ case IMGFMT_RGB24: return "RGB 24-bit";
+// case IMGFMT_RGB32: return "RGB 32-bit";
+ case IMGFMT_RGB48LE: return "RGB 48-bit LE";
+ case IMGFMT_RGB48BE: return "RGB 48-bit BE";
+ case IMGFMT_BGR1: return "BGR 1-bit";
+ case IMGFMT_BGR4: return "BGR 4-bit";
+ case IMGFMT_BG4B: return "BGR 4-bit per byte";
+ case IMGFMT_BGR8: return "BGR 8-bit";
+ case IMGFMT_BGR12: return "BGR 12-bit";
+ case IMGFMT_BGR15: return "BGR 15-bit";
+ case IMGFMT_BGR16: return "BGR 16-bit";
+ case IMGFMT_BGR24: return "BGR 24-bit";
+// case IMGFMT_BGR32: return "BGR 32-bit";
+ case IMGFMT_ABGR: return "ABGR";
+ case IMGFMT_BGRA: return "BGRA";
+ case IMGFMT_ARGB: return "ARGB";
+ case IMGFMT_RGBA: return "RGBA";
+ case IMGFMT_YVU9: return "Planar YVU9";
+ case IMGFMT_IF09: return "Planar IF09";
+ case IMGFMT_YV12: return "Planar YV12";
+ case IMGFMT_I420: return "Planar I420";
+ case IMGFMT_IYUV: return "Planar IYUV";
+ case IMGFMT_CLPL: return "Planar CLPL";
+ case IMGFMT_Y800: return "Planar Y800";
+ case IMGFMT_Y8: return "Planar Y8";
+ case IMGFMT_420P16_LE: return "Planar 420P 16-bit little-endian";
+ case IMGFMT_420P16_BE: return "Planar 420P 16-bit big-endian";
+ case IMGFMT_422P16_LE: return "Planar 422P 16-bit little-endian";
+ case IMGFMT_422P16_BE: return "Planar 422P 16-bit big-endian";
+ case IMGFMT_444P16_LE: return "Planar 444P 16-bit little-endian";
+ case IMGFMT_444P16_BE: return "Planar 444P 16-bit big-endian";
+ case IMGFMT_420A: return "Planar 420P with alpha";
+ case IMGFMT_444P: return "Planar 444P";
+ case IMGFMT_422P: return "Planar 422P";
+ case IMGFMT_411P: return "Planar 411P";
+ case IMGFMT_NV12: return "Planar NV12";
+ case IMGFMT_NV21: return "Planar NV21";
+ case IMGFMT_HM12: return "Planar NV12 Macroblock";
+ case IMGFMT_IUYV: return "Packed IUYV";
+ case IMGFMT_IY41: return "Packed IY41";
+ case IMGFMT_IYU1: return "Packed IYU1";
+ case IMGFMT_IYU2: return "Packed IYU2";
+ case IMGFMT_UYVY: return "Packed UYVY";
+ case IMGFMT_UYNV: return "Packed UYNV";
+ case IMGFMT_cyuv: return "Packed CYUV";
+ case IMGFMT_Y422: return "Packed Y422";
+ case IMGFMT_YUY2: return "Packed YUY2";
+ case IMGFMT_YUNV: return "Packed YUNV";
+ case IMGFMT_YVYU: return "Packed YVYU";
+ case IMGFMT_Y41P: return "Packed Y41P";
+ case IMGFMT_Y211: return "Packed Y211";
+ case IMGFMT_Y41T: return "Packed Y41T";
+ case IMGFMT_Y42T: return "Packed Y42T";
+ case IMGFMT_V422: return "Packed V422";
+ case IMGFMT_V655: return "Packed V655";
+ case IMGFMT_CLJR: return "Packed CLJR";
+ case IMGFMT_YUVP: return "Packed YUVP";
+ case IMGFMT_UYVP: return "Packed UYVP";
+ case IMGFMT_MPEGPES: return "Mpeg PES";
+ case IMGFMT_ZRMJPEGNI: return "Zoran MJPEG non-interlaced";
+ case IMGFMT_ZRMJPEGIT: return "Zoran MJPEG top field first";
+ case IMGFMT_ZRMJPEGIB: return "Zoran MJPEG bottom field first";
+ case IMGFMT_XVMC_MOCO_MPEG2: return "MPEG1/2 Motion Compensation";
+ case IMGFMT_XVMC_IDCT_MPEG2: return "MPEG1/2 Motion Compensation and IDCT";
+ case IMGFMT_VDPAU_MPEG1: return "MPEG1 VDPAU acceleration";
+ case IMGFMT_VDPAU_MPEG2: return "MPEG2 VDPAU acceleration";
+ case IMGFMT_VDPAU_H264: return "H.264 VDPAU acceleration";
+ case IMGFMT_VDPAU_MPEG4: return "MPEG-4 Part 2 VDPAU acceleration";
+ case IMGFMT_VDPAU_WMV3: return "WMV3 VDPAU acceleration";
+ case IMGFMT_VDPAU_VC1: return "VC1 VDPAU acceleration";
+ }
+ snprintf(unknown_format,20,"Unknown 0x%04x",format);
+ return unknown_format;
+}
+
+int mp_get_chroma_shift(int format, int *x_shift, int *y_shift)
+{
+ int xs = 0, ys = 0;
+ int bpp;
+ int bpp_factor = 1;
+ int err = 0;
+ switch (format) {
+ case IMGFMT_420P16_LE:
+ case IMGFMT_420P16_BE:
+ bpp_factor = 2;
+ case IMGFMT_420A:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YV12:
+ xs = 1;
+ ys = 1;
+ break;
+ case IMGFMT_IF09:
+ case IMGFMT_YVU9:
+ xs = 2;
+ ys = 2;
+ break;
+ case IMGFMT_444P16_LE:
+ case IMGFMT_444P16_BE:
+ bpp_factor = 2;
+ case IMGFMT_444P:
+ xs = 0;
+ ys = 0;
+ break;
+ case IMGFMT_422P16_LE:
+ case IMGFMT_422P16_BE:
+ bpp_factor = 2;
+ case IMGFMT_422P:
+ xs = 1;
+ ys = 0;
+ break;
+ case IMGFMT_411P:
+ xs = 2;
+ ys = 0;
+ break;
+ case IMGFMT_440P:
+ xs = 0;
+ ys = 1;
+ break;
+ case IMGFMT_Y8:
+ case IMGFMT_Y800:
+ xs = 31;
+ ys = 31;
+ break;
+ default:
+ err = 1;
+ break;
+ }
+ if (x_shift) *x_shift = xs;
+ if (y_shift) *y_shift = ys;
+ bpp = 8 + ((16 >> xs) >> ys);
+ if (format == IMGFMT_420A)
+ bpp += 8;
+ bpp *= bpp_factor;
+ return err ? 0 : bpp;
+}
diff --git a/libavfilter/libmpcodecs/img_format.h b/libavfilter/libmpcodecs/img_format.h
new file mode 100644
index 0000000000..c95ed4df3c
--- /dev/null
+++ b/libavfilter/libmpcodecs/img_format.h
@@ -0,0 +1,214 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_IMG_FORMAT_H
+#define MPLAYER_IMG_FORMAT_H
+
+#include "config.h"
+
+/* RGB/BGR Formats */
+
+#define IMGFMT_RGB_MASK 0xFFFFFF00
+#define IMGFMT_RGB (('R'<<24)|('G'<<16)|('B'<<8))
+#define IMGFMT_RGB1 (IMGFMT_RGB|1)
+#define IMGFMT_RGB4 (IMGFMT_RGB|4)
+#define IMGFMT_RGB4_CHAR (IMGFMT_RGB|4|128) // RGB4 with 1 pixel per byte
+#define IMGFMT_RGB8 (IMGFMT_RGB|8)
+#define IMGFMT_RGB12 (IMGFMT_RGB|12)
+#define IMGFMT_RGB15 (IMGFMT_RGB|15)
+#define IMGFMT_RGB16 (IMGFMT_RGB|16)
+#define IMGFMT_RGB24 (IMGFMT_RGB|24)
+#define IMGFMT_RGB32 (IMGFMT_RGB|32)
+#define IMGFMT_RGB48LE (IMGFMT_RGB|48)
+#define IMGFMT_RGB48BE (IMGFMT_RGB|48|128)
+
+#define IMGFMT_BGR_MASK 0xFFFFFF00
+#define IMGFMT_BGR (('B'<<24)|('G'<<16)|('R'<<8))
+#define IMGFMT_BGR1 (IMGFMT_BGR|1)
+#define IMGFMT_BGR4 (IMGFMT_BGR|4)
+#define IMGFMT_BGR4_CHAR (IMGFMT_BGR|4|128) // BGR4 with 1 pixel per byte
+#define IMGFMT_BGR8 (IMGFMT_BGR|8)
+#define IMGFMT_BGR12 (IMGFMT_BGR|12)
+#define IMGFMT_BGR15 (IMGFMT_BGR|15)
+#define IMGFMT_BGR16 (IMGFMT_BGR|16)
+#define IMGFMT_BGR24 (IMGFMT_BGR|24)
+#define IMGFMT_BGR32 (IMGFMT_BGR|32)
+
+#if HAVE_BIGENDIAN
+#define IMGFMT_ABGR IMGFMT_RGB32
+#define IMGFMT_BGRA (IMGFMT_RGB32|64)
+#define IMGFMT_ARGB IMGFMT_BGR32
+#define IMGFMT_RGBA (IMGFMT_BGR32|64)
+#define IMGFMT_RGB48NE IMGFMT_RGB48BE
+#define IMGFMT_RGB12BE IMGFMT_RGB12
+#define IMGFMT_RGB12LE (IMGFMT_RGB12|64)
+#define IMGFMT_RGB15BE IMGFMT_RGB15
+#define IMGFMT_RGB15LE (IMGFMT_RGB15|64)
+#define IMGFMT_RGB16BE IMGFMT_RGB16
+#define IMGFMT_RGB16LE (IMGFMT_RGB16|64)
+#define IMGFMT_BGR12BE IMGFMT_BGR12
+#define IMGFMT_BGR12LE (IMGFMT_BGR12|64)
+#define IMGFMT_BGR15BE IMGFMT_BGR15
+#define IMGFMT_BGR15LE (IMGFMT_BGR15|64)
+#define IMGFMT_BGR16BE IMGFMT_BGR16
+#define IMGFMT_BGR16LE (IMGFMT_BGR16|64)
+#else
+#define IMGFMT_ABGR (IMGFMT_BGR32|64)
+#define IMGFMT_BGRA IMGFMT_BGR32
+#define IMGFMT_ARGB (IMGFMT_RGB32|64)
+#define IMGFMT_RGBA IMGFMT_RGB32
+#define IMGFMT_RGB48NE IMGFMT_RGB48LE
+#define IMGFMT_RGB12BE (IMGFMT_RGB12|64)
+#define IMGFMT_RGB12LE IMGFMT_RGB12
+#define IMGFMT_RGB15BE (IMGFMT_RGB15|64)
+#define IMGFMT_RGB15LE IMGFMT_RGB15
+#define IMGFMT_RGB16BE (IMGFMT_RGB16|64)
+#define IMGFMT_RGB16LE IMGFMT_RGB16
+#define IMGFMT_BGR12BE (IMGFMT_BGR12|64)
+#define IMGFMT_BGR12LE IMGFMT_BGR12
+#define IMGFMT_BGR15BE (IMGFMT_BGR15|64)
+#define IMGFMT_BGR15LE IMGFMT_BGR15
+#define IMGFMT_BGR16BE (IMGFMT_BGR16|64)
+#define IMGFMT_BGR16LE IMGFMT_BGR16
+#endif
+
+/* old names for compatibility */
+#define IMGFMT_RG4B IMGFMT_RGB4_CHAR
+#define IMGFMT_BG4B IMGFMT_BGR4_CHAR
+
+#define IMGFMT_IS_RGB(fmt) (((fmt)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
+#define IMGFMT_IS_BGR(fmt) (((fmt)&IMGFMT_BGR_MASK)==IMGFMT_BGR)
+
+#define IMGFMT_RGB_DEPTH(fmt) ((fmt)&0x3F)
+#define IMGFMT_BGR_DEPTH(fmt) ((fmt)&0x3F)
+
+
+/* Planar YUV Formats */
+
+#define IMGFMT_YVU9 0x39555659
+#define IMGFMT_IF09 0x39304649
+#define IMGFMT_YV12 0x32315659
+#define IMGFMT_I420 0x30323449
+#define IMGFMT_IYUV 0x56555949
+#define IMGFMT_CLPL 0x4C504C43
+#define IMGFMT_Y800 0x30303859
+#define IMGFMT_Y8 0x20203859
+#define IMGFMT_NV12 0x3231564E
+#define IMGFMT_NV21 0x3132564E
+
+/* unofficial Planar Formats, FIXME if official 4CC exists */
+#define IMGFMT_444P 0x50343434
+#define IMGFMT_422P 0x50323234
+#define IMGFMT_411P 0x50313134
+#define IMGFMT_440P 0x50303434
+#define IMGFMT_HM12 0x32314D48
+
+// 4:2:0 planar with alpha
+#define IMGFMT_420A 0x41303234
+
+#define IMGFMT_444P16_LE 0x51343434
+#define IMGFMT_444P16_BE 0x34343451
+#define IMGFMT_422P16_LE 0x51323234
+#define IMGFMT_422P16_BE 0x34323251
+#define IMGFMT_420P16_LE 0x51303234
+#define IMGFMT_420P16_BE 0x34323051
+#if HAVE_BIGENDIAN
+#define IMGFMT_444P16 IMGFMT_444P16_BE
+#define IMGFMT_422P16 IMGFMT_422P16_BE
+#define IMGFMT_420P16 IMGFMT_420P16_BE
+#else
+#define IMGFMT_444P16 IMGFMT_444P16_LE
+#define IMGFMT_422P16 IMGFMT_422P16_LE
+#define IMGFMT_420P16 IMGFMT_420P16_LE
+#endif
+
+#define IMGFMT_IS_YUVP16_LE(fmt) (((fmt ^ IMGFMT_420P16_LE) & 0xff0000ff) == 0)
+#define IMGFMT_IS_YUVP16_BE(fmt) (((fmt ^ IMGFMT_420P16_BE) & 0xff0000ff) == 0)
+#define IMGFMT_IS_YUVP16_NE(fmt) (((fmt ^ IMGFMT_420P16 ) & 0xff0000ff) == 0)
+#define IMGFMT_IS_YUVP16(fmt) (IMGFMT_IS_YUVP16_LE(fmt) || IMGFMT_IS_YUVP16_BE(fmt))
+
+/* Packed YUV Formats */
+
+#define IMGFMT_IUYV 0x56595549
+#define IMGFMT_IY41 0x31435949
+#define IMGFMT_IYU1 0x31555949
+#define IMGFMT_IYU2 0x32555949
+#define IMGFMT_UYVY 0x59565955
+#define IMGFMT_UYNV 0x564E5955
+#define IMGFMT_cyuv 0x76757963
+#define IMGFMT_Y422 0x32323459
+#define IMGFMT_YUY2 0x32595559
+#define IMGFMT_YUNV 0x564E5559
+#define IMGFMT_YVYU 0x55595659
+#define IMGFMT_Y41P 0x50313459
+#define IMGFMT_Y211 0x31313259
+#define IMGFMT_Y41T 0x54313459
+#define IMGFMT_Y42T 0x54323459
+#define IMGFMT_V422 0x32323456
+#define IMGFMT_V655 0x35353656
+#define IMGFMT_CLJR 0x524A4C43
+#define IMGFMT_YUVP 0x50565559
+#define IMGFMT_UYVP 0x50565955
+
+/* Compressed Formats */
+#define IMGFMT_MPEGPES (('M'<<24)|('P'<<16)|('E'<<8)|('S'))
+#define IMGFMT_MJPEG (('M')|('J'<<8)|('P'<<16)|('G'<<24))
+/* Formats that are understood by zoran chips, we include
+ * non-interlaced, interlaced top-first, interlaced bottom-first */
+#define IMGFMT_ZRMJPEGNI (('Z'<<24)|('R'<<16)|('N'<<8)|('I'))
+#define IMGFMT_ZRMJPEGIT (('Z'<<24)|('R'<<16)|('I'<<8)|('T'))
+#define IMGFMT_ZRMJPEGIB (('Z'<<24)|('R'<<16)|('I'<<8)|('B'))
+
+// I think that this code could not be used by any other codec/format
+#define IMGFMT_XVMC 0x1DC70000
+#define IMGFMT_XVMC_MASK 0xFFFF0000
+#define IMGFMT_IS_XVMC(fmt) (((fmt)&IMGFMT_XVMC_MASK)==IMGFMT_XVMC)
+//these are chroma420
+#define IMGFMT_XVMC_MOCO_MPEG2 (IMGFMT_XVMC|0x02)
+#define IMGFMT_XVMC_IDCT_MPEG2 (IMGFMT_XVMC|0x82)
+
+// VDPAU specific format.
+#define IMGFMT_VDPAU 0x1DC80000
+#define IMGFMT_VDPAU_MASK 0xFFFF0000
+#define IMGFMT_IS_VDPAU(fmt) (((fmt)&IMGFMT_VDPAU_MASK)==IMGFMT_VDPAU)
+#define IMGFMT_VDPAU_MPEG1 (IMGFMT_VDPAU|0x01)
+#define IMGFMT_VDPAU_MPEG2 (IMGFMT_VDPAU|0x02)
+#define IMGFMT_VDPAU_H264 (IMGFMT_VDPAU|0x03)
+#define IMGFMT_VDPAU_WMV3 (IMGFMT_VDPAU|0x04)
+#define IMGFMT_VDPAU_VC1 (IMGFMT_VDPAU|0x05)
+#define IMGFMT_VDPAU_MPEG4 (IMGFMT_VDPAU|0x06)
+
+#define IMGFMT_IS_HWACCEL(fmt) (IMGFMT_IS_VDPAU(fmt) || IMGFMT_IS_XVMC(fmt))
+
+typedef struct {
+ void* data;
+ int size;
+ int id; // stream id. usually 0x1E0
+ int timestamp; // pts, 90000 Hz counter based
+} vo_mpegpes_t;
+
+const char *vo_format_name(int format);
+
+/**
+ * Calculates the scale shifts for the chroma planes for planar YUV
+ *
+ * \return bits-per-pixel for format if successful (i.e. format is 3 or 4-planes planar YUV), 0 otherwise
+ */
+int mp_get_chroma_shift(int format, int *x_shift, int *y_shift);
+
+#endif /* MPLAYER_IMG_FORMAT_H */
diff --git a/libavfilter/libmpcodecs/libvo/fastmemcpy.h b/libavfilter/libmpcodecs/libvo/fastmemcpy.h
new file mode 100644
index 0000000000..54980a65ac
--- /dev/null
+++ b/libavfilter/libmpcodecs/libvo/fastmemcpy.h
@@ -0,0 +1,99 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * MPlayer 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with MPlayer; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MPLAYER_FASTMEMCPY_H
+#define MPLAYER_FASTMEMCPY_H
+
+#include <inttypes.h>
+#include <string.h>
+#include <stddef.h>
+
+void * fast_memcpy(void * to, const void * from, size_t len);
+void * mem2agpcpy(void * to, const void * from, size_t len);
+
+#if ! defined(CONFIG_FASTMEMCPY) || ! (HAVE_MMX || HAVE_MMX2 || HAVE_AMD3DNOW /* || HAVE_SSE || HAVE_SSE2 */)
+#define mem2agpcpy(a,b,c) memcpy(a,b,c)
+#define fast_memcpy(a,b,c) memcpy(a,b,c)
+#endif
+
+static inline void * mem2agpcpy_pic(void * dst, const void * src, int bytesPerLine, int height, int dstStride, int srcStride)
+{
+ int i;
+ void *retval=dst;
+
+ if(dstStride == srcStride)
+ {
+ if (srcStride < 0) {
+ src = (uint8_t*)src + (height-1)*srcStride;
+ dst = (uint8_t*)dst + (height-1)*dstStride;
+ srcStride = -srcStride;
+ }
+
+ mem2agpcpy(dst, src, srcStride*height);
+ }
+ else
+ {
+ for(i=0; i<height; i++)
+ {
+ mem2agpcpy(dst, src, bytesPerLine);
+ src = (uint8_t*)src + srcStride;
+ dst = (uint8_t*)dst + dstStride;
+ }
+ }
+
+ return retval;
+}
+
+#define memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 0)
+#define my_memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 1)
+
+/**
+ * \param limit2width always skip data between end of line and start of next
+ * instead of copying the full block when strides are the same
+ */
+static inline void * memcpy_pic2(void * dst, const void * src,
+ int bytesPerLine, int height,
+ int dstStride, int srcStride, int limit2width)
+{
+ int i;
+ void *retval=dst;
+
+ if(!limit2width && dstStride == srcStride)
+ {
+ if (srcStride < 0) {
+ src = (uint8_t*)src + (height-1)*srcStride;
+ dst = (uint8_t*)dst + (height-1)*dstStride;
+ srcStride = -srcStride;
+ }
+
+ fast_memcpy(dst, src, srcStride*height);
+ }
+ else
+ {
+ for(i=0; i<height; i++)
+ {
+ fast_memcpy(dst, src, bytesPerLine);
+ src = (uint8_t*)src + srcStride;
+ dst = (uint8_t*)dst + dstStride;
+ }
+ }
+
+ return retval;
+}
+
+#endif /* MPLAYER_FASTMEMCPY_H */
diff --git a/libavfilter/libmpcodecs/libvo/video_out.h b/libavfilter/libmpcodecs/libvo/video_out.h
new file mode 100644
index 0000000000..cbbea66445
--- /dev/null
+++ b/libavfilter/libmpcodecs/libvo/video_out.h
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) Aaron Holtzman - Aug 1999
+ * Strongly modified, most parts rewritten: A'rpi/ESP-team - 2000-2001
+ * (C) MPlayer developers
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_VIDEO_OUT_H
+#define MPLAYER_VIDEO_OUT_H
+
+#include <inttypes.h>
+#include <stdarg.h>
+
+//#include "sub/font_load.h"
+#include "libmpcodecs/img_format.h"
+//#include "vidix/vidix.h"
+
+#define VO_EVENT_EXPOSE 1
+#define VO_EVENT_RESIZE 2
+#define VO_EVENT_KEYPRESS 4
+#define VO_EVENT_REINIT 8
+#define VO_EVENT_MOVE 16
+
+/* Obsolete: VOCTRL_QUERY_VAA 1 */
+/* does the device support the required format */
+#define VOCTRL_QUERY_FORMAT 2
+/* signal a device reset seek */
+#define VOCTRL_RESET 3
+/* true if vo driver can use GUI created windows */
+#define VOCTRL_GUISUPPORT 4
+#define VOCTRL_GUI_NOWINDOW 19
+/* used to switch to fullscreen */
+#define VOCTRL_FULLSCREEN 5
+/* signal a device pause */
+#define VOCTRL_PAUSE 7
+/* start/resume playback */
+#define VOCTRL_RESUME 8
+/* libmpcodecs direct rendering: */
+#define VOCTRL_GET_IMAGE 9
+#define VOCTRL_DRAW_IMAGE 13
+#define VOCTRL_SET_SPU_PALETTE 14
+/* decoding ahead: */
+#define VOCTRL_GET_NUM_FRAMES 10
+#define VOCTRL_GET_FRAME_NUM 11
+#define VOCTRL_SET_FRAME_NUM 12
+#define VOCTRL_GET_PANSCAN 15
+#define VOCTRL_SET_PANSCAN 16
+/* equalizer controls */
+#define VOCTRL_SET_EQUALIZER 17
+#define VOCTRL_GET_EQUALIZER 18
+//#define VOCTRL_GUI_NOWINDOW 19
+/* Frame duplication */
+#define VOCTRL_DUPLICATE_FRAME 20
+// ... 21
+#define VOCTRL_START_SLICE 21
+
+#define VOCTRL_ONTOP 25
+#define VOCTRL_ROOTWIN 26
+#define VOCTRL_BORDER 27
+#define VOCTRL_DRAW_EOSD 28
+#define VOCTRL_GET_EOSD_RES 29
+
+#define VOCTRL_SET_DEINTERLACE 30
+#define VOCTRL_GET_DEINTERLACE 31
+
+#define VOCTRL_UPDATE_SCREENINFO 32
+
+// Vo can be used by xover
+#define VOCTRL_XOVERLAY_SUPPORT 22
+
+#define VOCTRL_XOVERLAY_SET_COLORKEY 24
+typedef struct {
+ uint32_t x11; // The raw x11 color
+ uint16_t r,g,b;
+} mp_colorkey_t;
+
+#define VOCTRL_XOVERLAY_SET_WIN 23
+typedef struct {
+ int x,y;
+ int w,h;
+} mp_win_t;
+
+#define VO_TRUE 1
+#define VO_FALSE 0
+#define VO_ERROR -1
+#define VO_NOTAVAIL -2
+#define VO_NOTIMPL -3
+
+#define VOFLAG_FULLSCREEN 0x01
+#define VOFLAG_MODESWITCHING 0x02
+#define VOFLAG_SWSCALE 0x04
+#define VOFLAG_FLIPPING 0x08
+#define VOFLAG_HIDDEN 0x10 //< Use to create a hidden window
+#define VOFLAG_STEREO 0x20 //< Use to create a stereo-capable window
+#define VOFLAG_XOVERLAY_SUB_VO 0x10000
+
+typedef struct vo_info_s
+{
+ /* driver name ("Matrox Millennium G200/G400" */
+ const char *name;
+ /* short name (for config strings) ("mga") */
+ const char *short_name;
+ /* author ("Aaron Holtzman <aholtzma@ess.engr.uvic.ca>") */
+ const char *author;
+ /* any additional comments */
+ const char *comment;
+} vo_info_t;
+
+typedef struct vo_functions_s
+{
+ const vo_info_t *info;
+ /*
+ * Preinitializes driver (real INITIALIZATION)
+ * arg - currently it's vo_subdevice
+ * returns: zero on successful initialization, non-zero on error.
+ */
+ int (*preinit)(const char *arg);
+ /*
+ * Initialize (means CONFIGURE) the display driver.
+ * params:
+ * width,height: image source size
+ * d_width,d_height: size of the requested window size, just a hint
+ * fullscreen: flag, 0=windowd 1=fullscreen, just a hint
+ * title: window title, if available
+ * format: fourcc of pixel format
+ * returns : zero on successful initialization, non-zero on error.
+ */
+ int (*config)(uint32_t width, uint32_t height, uint32_t d_width,
+ uint32_t d_height, uint32_t fullscreen, char *title,
+ uint32_t format);
+
+ /*
+ * Control interface
+ */
+ int (*control)(uint32_t request, void *data, ...);
+
+ /*
+ * Display a new RGB/BGR frame of the video to the screen.
+ * params:
+ * src[0] - pointer to the image
+ */
+ int (*draw_frame)(uint8_t *src[]);
+
+ /*
+ * Draw a planar YUV slice to the buffer:
+ * params:
+ * src[3] = source image planes (Y,U,V)
+ * stride[3] = source image planes line widths (in bytes)
+ * w,h = width*height of area to be copied (in Y pixels)
+ * x,y = position at the destination image (in Y pixels)
+ */
+ int (*draw_slice)(uint8_t *src[], int stride[], int w,int h, int x,int y);
+
+ /*
+ * Draws OSD to the screen buffer
+ */
+ void (*draw_osd)(void);
+
+ /*
+ * Blit/Flip buffer to the screen. Must be called after each frame!
+ */
+ void (*flip_page)(void);
+
+ /*
+ * This func is called after every frames to handle keyboard and
+ * other events. It's called in PAUSE mode too!
+ */
+ void (*check_events)(void);
+
+ /*
+ * Closes driver. Should restore the original state of the system.
+ */
+ void (*uninit)(void);
+} vo_functions_t;
+
+const vo_functions_t* init_best_video_out(char** vo_list);
+int config_video_out(const vo_functions_t *vo, uint32_t width, uint32_t height,
+ uint32_t d_width, uint32_t d_height, uint32_t flags,
+ char *title, uint32_t format);
+void list_video_out(void);
+
+// NULL terminated array of all drivers
+extern const vo_functions_t* const video_out_drivers[];
+
+extern int vo_flags;
+
+extern int vo_config_count;
+
+extern int xinerama_screen;
+extern int xinerama_x;
+extern int xinerama_y;
+
+// correct resolution/bpp on screen: (should be autodetected by vo_init())
+extern int vo_depthonscreen;
+extern int vo_screenwidth;
+extern int vo_screenheight;
+
+// requested resolution/bpp: (-x -y -bpp options)
+extern int vo_dx;
+extern int vo_dy;
+extern int vo_dwidth;
+extern int vo_dheight;
+extern int vo_dbpp;
+
+extern int vo_grabpointer;
+extern int vo_doublebuffering;
+extern int vo_directrendering;
+extern int vo_vsync;
+extern int vo_fs;
+extern int vo_fsmode;
+extern float vo_panscan;
+extern int vo_adapter_num;
+extern int vo_refresh_rate;
+extern int vo_keepaspect;
+extern int vo_rootwin;
+extern int vo_ontop;
+extern int vo_border;
+
+extern int vo_gamma_gamma;
+extern int vo_gamma_brightness;
+extern int vo_gamma_saturation;
+extern int vo_gamma_contrast;
+extern int vo_gamma_hue;
+extern int vo_gamma_red_intensity;
+extern int vo_gamma_green_intensity;
+extern int vo_gamma_blue_intensity;
+
+extern int vo_nomouse_input;
+extern int enable_mouse_movements;
+
+extern int vo_pts;
+extern float vo_fps;
+
+extern char *vo_subdevice;
+
+extern int vo_colorkey;
+
+extern char *vo_winname;
+extern char *vo_wintitle;
+
+extern int64_t WinID;
+
+typedef struct {
+ float min;
+ float max;
+ } range_t;
+
+float range_max(range_t *r);
+int in_range(range_t *r, float f);
+range_t *str2range(char *s);
+extern char *monitor_hfreq_str;
+extern char *monitor_vfreq_str;
+extern char *monitor_dotclock_str;
+
+struct mp_keymap {
+ int from;
+ int to;
+};
+int lookup_keymap_table(const struct mp_keymap *map, int key);
+struct vo_rect {
+ int left, right, top, bottom, width, height;
+};
+void calc_src_dst_rects(int src_width, int src_height, struct vo_rect *src, struct vo_rect *dst,
+ struct vo_rect *borders, const struct vo_rect *crop);
+void vo_mouse_movement(int posx, int posy);
+
+static inline int aspect_scaling(void)
+{
+ return vo_fs;
+}
+
+#endif /* MPLAYER_VIDEO_OUT_H */
diff --git a/libavfilter/libmpcodecs/mp_image.c b/libavfilter/libmpcodecs/mp_image.c
new file mode 100644
index 0000000000..397bebfa00
--- /dev/null
+++ b/libavfilter/libmpcodecs/mp_image.c
@@ -0,0 +1,200 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "libmpcodecs/img_format.h"
+#include "libmpcodecs/mp_image.h"
+
+#include "libvo/fastmemcpy.h"
+#include "libavutil/mem.h"
+
+void mp_image_alloc_planes(mp_image_t *mpi) {
+ // IF09 - allocate space for 4. plane delta info - unused
+ if (mpi->imgfmt == IMGFMT_IF09) {
+ mpi->planes[0]=av_malloc(mpi->bpp*mpi->width*(mpi->height+2)/8+
+ mpi->chroma_width*mpi->chroma_height);
+ } else
+ mpi->planes[0]=av_malloc(mpi->bpp*mpi->width*(mpi->height+2)/8);
+ if (mpi->flags&MP_IMGFLAG_PLANAR) {
+ int bpp = IMGFMT_IS_YUVP16(mpi->imgfmt)? 2 : 1;
+ // YV12/I420/YVU9/IF09. feel free to add other planar formats here...
+ mpi->stride[0]=mpi->stride[3]=bpp*mpi->width;
+ if(mpi->num_planes > 2){
+ mpi->stride[1]=mpi->stride[2]=bpp*mpi->chroma_width;
+ if(mpi->flags&MP_IMGFLAG_SWAPPED){
+ // I420/IYUV (Y,U,V)
+ mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->height;
+ mpi->planes[2]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
+ if (mpi->num_planes > 3)
+ mpi->planes[3]=mpi->planes[2]+mpi->stride[2]*mpi->chroma_height;
+ } else {
+ // YV12,YVU9,IF09 (Y,V,U)
+ mpi->planes[2]=mpi->planes[0]+mpi->stride[0]*mpi->height;
+ mpi->planes[1]=mpi->planes[2]+mpi->stride[1]*mpi->chroma_height;
+ if (mpi->num_planes > 3)
+ mpi->planes[3]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
+ }
+ } else {
+ // NV12/NV21
+ mpi->stride[1]=mpi->chroma_width;
+ mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->height;
+ }
+ } else {
+ mpi->stride[0]=mpi->width*mpi->bpp/8;
+ if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
+ mpi->planes[1] = av_malloc(1024);
+ }
+ mpi->flags|=MP_IMGFLAG_ALLOCATED;
+}
+
+mp_image_t* alloc_mpi(int w, int h, unsigned long int fmt) {
+ mp_image_t* mpi = new_mp_image(w,h);
+
+ mp_image_setfmt(mpi,fmt);
+ mp_image_alloc_planes(mpi);
+
+ return mpi;
+}
+
+void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi) {
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ memcpy_pic(dmpi->planes[0],mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0],mpi->stride[0]);
+ memcpy_pic(dmpi->planes[1],mpi->planes[1], mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1],mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2],mpi->stride[2]);
+ } else {
+ memcpy_pic(dmpi->planes[0],mpi->planes[0],
+ mpi->w*(dmpi->bpp/8), mpi->h,
+ dmpi->stride[0],mpi->stride[0]);
+ }
+}
+
+void mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt){
+ mpi->flags&=~(MP_IMGFLAG_PLANAR|MP_IMGFLAG_YUV|MP_IMGFLAG_SWAPPED);
+ mpi->imgfmt=out_fmt;
+ // compressed formats
+ if(out_fmt == IMGFMT_MPEGPES ||
+ out_fmt == IMGFMT_ZRMJPEGNI || out_fmt == IMGFMT_ZRMJPEGIT || out_fmt == IMGFMT_ZRMJPEGIB ||
+ IMGFMT_IS_HWACCEL(out_fmt)){
+ mpi->bpp=0;
+ return;
+ }
+ mpi->num_planes=1;
+ if (IMGFMT_IS_RGB(out_fmt)) {
+ if (IMGFMT_RGB_DEPTH(out_fmt) < 8 && !(out_fmt&128))
+ mpi->bpp = IMGFMT_RGB_DEPTH(out_fmt);
+ else
+ mpi->bpp=(IMGFMT_RGB_DEPTH(out_fmt)+7)&(~7);
+ return;
+ }
+ if (IMGFMT_IS_BGR(out_fmt)) {
+ if (IMGFMT_BGR_DEPTH(out_fmt) < 8 && !(out_fmt&128))
+ mpi->bpp = IMGFMT_BGR_DEPTH(out_fmt);
+ else
+ mpi->bpp=(IMGFMT_BGR_DEPTH(out_fmt)+7)&(~7);
+ mpi->flags|=MP_IMGFLAG_SWAPPED;
+ return;
+ }
+ mpi->flags|=MP_IMGFLAG_YUV;
+ mpi->num_planes=3;
+ if (mp_get_chroma_shift(out_fmt, NULL, NULL)) {
+ mpi->flags|=MP_IMGFLAG_PLANAR;
+ mpi->bpp = mp_get_chroma_shift(out_fmt, &mpi->chroma_x_shift, &mpi->chroma_y_shift);
+ mpi->chroma_width = mpi->width >> mpi->chroma_x_shift;
+ mpi->chroma_height = mpi->height >> mpi->chroma_y_shift;
+ }
+ switch(out_fmt){
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ mpi->flags|=MP_IMGFLAG_SWAPPED;
+ case IMGFMT_YV12:
+ return;
+ case IMGFMT_420A:
+ case IMGFMT_IF09:
+ mpi->num_planes=4;
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ case IMGFMT_440P:
+ case IMGFMT_444P16_LE:
+ case IMGFMT_444P16_BE:
+ case IMGFMT_422P16_LE:
+ case IMGFMT_422P16_BE:
+ case IMGFMT_420P16_LE:
+ case IMGFMT_420P16_BE:
+ return;
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ /* they're planar ones, but for easier handling use them as packed */
+ mpi->flags&=~MP_IMGFLAG_PLANAR;
+ mpi->num_planes=1;
+ return;
+ case IMGFMT_UYVY:
+ mpi->flags|=MP_IMGFLAG_SWAPPED;
+ case IMGFMT_YUY2:
+ mpi->bpp=16;
+ mpi->num_planes=1;
+ return;
+ case IMGFMT_NV12:
+ mpi->flags|=MP_IMGFLAG_SWAPPED;
+ case IMGFMT_NV21:
+ mpi->flags|=MP_IMGFLAG_PLANAR;
+ mpi->bpp=12;
+ mpi->num_planes=2;
+ mpi->chroma_width=(mpi->width>>0);
+ mpi->chroma_height=(mpi->height>>1);
+ mpi->chroma_x_shift=0;
+ mpi->chroma_y_shift=1;
+ return;
+ }
+ mp_msg(MSGT_DECVIDEO,MSGL_WARN,"mp_image: unknown out_fmt: 0x%X\n",out_fmt);
+ mpi->bpp=0;
+}
+
+mp_image_t* new_mp_image(int w,int h){
+ mp_image_t* mpi = malloc(sizeof(mp_image_t));
+ if(!mpi) return NULL; // error!
+ memset(mpi,0,sizeof(mp_image_t));
+ mpi->width=mpi->w=w;
+ mpi->height=mpi->h=h;
+ return mpi;
+}
+
+void free_mp_image(mp_image_t* mpi){
+ if(!mpi) return;
+ if(mpi->flags&MP_IMGFLAG_ALLOCATED){
+ /* becouse we allocate the whole image in once */
+ av_free(mpi->planes[0]);
+ if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
+ av_free(mpi->planes[1]);
+ }
+ free(mpi);
+}
+
diff --git a/libavfilter/libmpcodecs/mp_image.h b/libavfilter/libmpcodecs/mp_image.h
new file mode 100644
index 0000000000..7c56880bb6
--- /dev/null
+++ b/libavfilter/libmpcodecs/mp_image.h
@@ -0,0 +1,137 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_MP_IMAGE_H
+#define MPLAYER_MP_IMAGE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mp_msg.h"
+
+//--------- codec's requirements (filled by the codec/vf) ---------
+
+//--- buffer content restrictions:
+// set if buffer content shouldn't be modified:
+#define MP_IMGFLAG_PRESERVE 0x01
+// set if buffer content will be READ for next frame's MC: (I/P mpeg frames)
+#define MP_IMGFLAG_READABLE 0x02
+
+//--- buffer width/stride/plane restrictions: (used for direct rendering)
+// stride _have_to_ be aligned to MB boundary: [for DR restrictions]
+#define MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE 0x4
+// stride should be aligned to MB boundary: [for buffer allocation]
+#define MP_IMGFLAG_PREFER_ALIGNED_STRIDE 0x8
+// codec accept any stride (>=width):
+#define MP_IMGFLAG_ACCEPT_STRIDE 0x10
+// codec accept any width (width*bpp=stride -> stride%bpp==0) (>=width):
+#define MP_IMGFLAG_ACCEPT_WIDTH 0x20
+//--- for planar formats only:
+// uses only stride[0], and stride[1]=stride[2]=stride[0]>>mpi->chroma_x_shift
+#define MP_IMGFLAG_COMMON_STRIDE 0x40
+// uses only planes[0], and calculates planes[1,2] from width,height,imgfmt
+#define MP_IMGFLAG_COMMON_PLANE 0x80
+
+#define MP_IMGFLAGMASK_RESTRICTIONS 0xFF
+
+//--------- color info (filled by mp_image_setfmt() ) -----------
+// set if number of planes > 1
+#define MP_IMGFLAG_PLANAR 0x100
+// set if it's YUV colorspace
+#define MP_IMGFLAG_YUV 0x200
+// set if it's swapped (BGR or YVU) plane/byteorder
+#define MP_IMGFLAG_SWAPPED 0x400
+// set if you want memory for palette allocated and managed by vf_get_image etc.
+#define MP_IMGFLAG_RGB_PALETTE 0x800
+
+#define MP_IMGFLAGMASK_COLORS 0xF00
+
+// codec uses drawing/rendering callbacks (draw_slice()-like thing, DR method 2)
+// [the codec will set this flag if it supports callbacks, and the vo _may_
+// clear it in get_image() if draw_slice() not implemented]
+#define MP_IMGFLAG_DRAW_CALLBACK 0x1000
+// set if it's in video buffer/memory: [set by vo/vf's get_image() !!!]
+#define MP_IMGFLAG_DIRECT 0x2000
+// set if buffer is allocated (used in destination images):
+#define MP_IMGFLAG_ALLOCATED 0x4000
+
+// buffer type was printed (do NOT set this flag - it's for INTERNAL USE!!!)
+#define MP_IMGFLAG_TYPE_DISPLAYED 0x8000
+
+// codec doesn't support any form of direct rendering - it has own buffer
+// allocation. so we just export its buffer pointers:
+#define MP_IMGTYPE_EXPORT 0
+// codec requires a static WO buffer, but it does only partial updates later:
+#define MP_IMGTYPE_STATIC 1
+// codec just needs some WO memory, where it writes/copies the whole frame to:
+#define MP_IMGTYPE_TEMP 2
+// I+P type, requires 2+ independent static R/W buffers
+#define MP_IMGTYPE_IP 3
+// I+P+B type, requires 2+ independent static R/W and 1+ temp WO buffers
+#define MP_IMGTYPE_IPB 4
+// Upper 16 bits give desired buffer number, -1 means get next available
+#define MP_IMGTYPE_NUMBERED 5
+// Doesn't need any buffer, incomplete image (probably a first field only)
+// we need this type to be able to differentiate between half frames and
+// all other cases
+#define MP_IMGTYPE_INCOMPLETE 6
+
+#define MP_MAX_PLANES 4
+
+#define MP_IMGFIELD_ORDERED 0x01
+#define MP_IMGFIELD_TOP_FIRST 0x02
+#define MP_IMGFIELD_REPEAT_FIRST 0x04
+#define MP_IMGFIELD_TOP 0x08
+#define MP_IMGFIELD_BOTTOM 0x10
+#define MP_IMGFIELD_INTERLACED 0x20
+
+typedef struct mp_image {
+ unsigned int flags;
+ unsigned char type;
+ int number;
+ unsigned char bpp; // bits/pixel. NOT depth! for RGB it will be n*8
+ unsigned int imgfmt;
+ int width,height; // stored dimensions
+ int x,y,w,h; // visible dimensions
+ unsigned char* planes[MP_MAX_PLANES];
+ int stride[MP_MAX_PLANES];
+ char * qscale;
+ int qstride;
+ int pict_type; // 0->unknown, 1->I, 2->P, 3->B
+ int fields;
+ int qscale_type; // 0->mpeg1/4/h263, 1->mpeg2
+ int num_planes;
+ /* these are only used by planar formats Y,U(Cb),V(Cr) */
+ int chroma_width;
+ int chroma_height;
+ int chroma_x_shift; // horizontal
+ int chroma_y_shift; // vertical
+ int usage_count;
+ /* for private use by filter or vo driver (to store buffer id or dmpi) */
+ void* priv;
+} mp_image_t;
+
+void mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt);
+mp_image_t* new_mp_image(int w,int h);
+void free_mp_image(mp_image_t* mpi);
+
+mp_image_t* alloc_mpi(int w, int h, unsigned long int fmt);
+void mp_image_alloc_planes(mp_image_t *mpi);
+void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi);
+
+#endif /* MPLAYER_MP_IMAGE_H */
diff --git a/libavfilter/libmpcodecs/mp_msg.h b/libavfilter/libmpcodecs/mp_msg.h
new file mode 100644
index 0000000000..7b6405b883
--- /dev/null
+++ b/libavfilter/libmpcodecs/mp_msg.h
@@ -0,0 +1,164 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_MP_MSG_H
+#define MPLAYER_MP_MSG_H
+
+#include <stdarg.h>
+
+// defined in mplayer.c and mencoder.c
+extern int verbose;
+
+// verbosity elevel:
+
+/* Only messages level MSGL_FATAL-MSGL_STATUS should be translated,
+ * messages level MSGL_V and above should not be translated. */
+
+#define MSGL_FATAL 0 // will exit/abort
+#define MSGL_ERR 1 // continues
+#define MSGL_WARN 2 // only warning
+#define MSGL_HINT 3 // short help message
+#define MSGL_INFO 4 // -quiet
+#define MSGL_STATUS 5 // v=0
+#define MSGL_V 6 // v=1
+#define MSGL_DBG2 7 // v=2
+#define MSGL_DBG3 8 // v=3
+#define MSGL_DBG4 9 // v=4
+#define MSGL_DBG5 10 // v=5
+
+#define MSGL_FIXME 1 // for conversions from printf where the appropriate MSGL is not known; set equal to ERR for obtrusiveness
+#define MSGT_FIXME 0 // for conversions from printf where the appropriate MSGT is not known; set equal to GLOBAL for obtrusiveness
+
+// code/module:
+
+#define MSGT_GLOBAL 0 // common player stuff errors
+#define MSGT_CPLAYER 1 // console player (mplayer.c)
+#define MSGT_GPLAYER 2 // gui player
+
+#define MSGT_VO 3 // libvo
+#define MSGT_AO 4 // libao
+
+#define MSGT_DEMUXER 5 // demuxer.c (general stuff)
+#define MSGT_DS 6 // demux stream (add/read packet etc)
+#define MSGT_DEMUX 7 // fileformat-specific stuff (demux_*.c)
+#define MSGT_HEADER 8 // fileformat-specific header (*header.c)
+
+#define MSGT_AVSYNC 9 // mplayer.c timer stuff
+#define MSGT_AUTOQ 10 // mplayer.c auto-quality stuff
+
+#define MSGT_CFGPARSER 11 // cfgparser.c
+
+#define MSGT_DECAUDIO 12 // av decoder
+#define MSGT_DECVIDEO 13
+
+#define MSGT_SEEK 14 // seeking code
+#define MSGT_WIN32 15 // win32 dll stuff
+#define MSGT_OPEN 16 // open.c (stream opening)
+#define MSGT_DVD 17 // open.c (DVD init/read/seek)
+
+#define MSGT_PARSEES 18 // parse_es.c (mpeg stream parser)
+#define MSGT_LIRC 19 // lirc_mp.c and input lirc driver
+
+#define MSGT_STREAM 20 // stream.c
+#define MSGT_CACHE 21 // cache2.c
+
+#define MSGT_MENCODER 22
+
+#define MSGT_XACODEC 23 // XAnim codecs
+
+#define MSGT_TV 24 // TV input subsystem
+
+#define MSGT_OSDEP 25 // OS-dependent parts
+
+#define MSGT_SPUDEC 26 // spudec.c
+
+#define MSGT_PLAYTREE 27 // Playtree handeling (playtree.c, playtreeparser.c)
+
+#define MSGT_INPUT 28
+
+#define MSGT_VFILTER 29
+
+#define MSGT_OSD 30
+
+#define MSGT_NETWORK 31
+
+#define MSGT_CPUDETECT 32
+
+#define MSGT_CODECCFG 33
+
+#define MSGT_SWS 34
+
+#define MSGT_VOBSUB 35
+#define MSGT_SUBREADER 36
+
+#define MSGT_AFILTER 37 // Audio filter messages
+
+#define MSGT_NETST 38 // Netstream
+
+#define MSGT_MUXER 39 // muxer layer
+
+#define MSGT_OSD_MENU 40
+
+#define MSGT_IDENTIFY 41 // -identify output
+
+#define MSGT_RADIO 42
+
+#define MSGT_ASS 43 // libass messages
+
+#define MSGT_LOADER 44 // dll loader messages
+
+#define MSGT_STATUSLINE 45 // playback/encoding status line
+
+#define MSGT_TELETEXT 46 // Teletext decoder
+
+#define MSGT_MAX 64
+
+
+extern char *mp_msg_charset;
+extern int mp_msg_color;
+extern int mp_msg_module;
+
+extern int mp_msg_levels[MSGT_MAX];
+extern int mp_msg_level_all;
+
+
+void mp_msg_init(void);
+int mp_msg_test(int mod, int lev);
+
+#include "config.h"
+
+void mp_msg_va(int mod, int lev, const char *format, va_list va);
+#ifdef __GNUC__
+void mp_msg(int mod, int lev, const char *format, ... ) __attribute__ ((format (printf, 3, 4)));
+# ifdef MP_DEBUG
+# define mp_dbg(mod,lev, args... ) mp_msg(mod, lev, ## args )
+# else
+# define mp_dbg(mod,lev, args... ) /* only useful for developers */
+# endif
+#else // not GNU C
+void mp_msg(int mod, int lev, const char *format, ... );
+# ifdef MP_DEBUG
+# define mp_dbg(mod,lev, ... ) mp_msg(mod, lev, __VA_ARGS__)
+# else
+# define mp_dbg(mod,lev, ... ) /* only useful for developers */
+# endif
+#endif /* __GNUC__ */
+
+const char* filename_recode(const char* filename);
+
+#endif /* MPLAYER_MP_MSG_H */
diff --git a/libavfilter/libmpcodecs/mpbswap.h b/libavfilter/libmpcodecs/mpbswap.h
new file mode 100644
index 0000000000..7ec7946054
--- /dev/null
+++ b/libavfilter/libmpcodecs/mpbswap.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_MPBSWAP_H
+#define MPLAYER_MPBSWAP_H
+
+#include <sys/types.h>
+#include "config.h"
+#include "libavutil/bswap.h"
+
+#define bswap_16(v) av_bswap16(v)
+#define bswap_32(v) av_bswap32(v)
+#define le2me_16(v) av_le2ne16(v)
+#define le2me_32(v) av_le2ne32(v)
+#define le2me_64(v) av_le2ne64(v)
+#define be2me_16(v) av_be2ne16(v)
+#define be2me_32(v) av_be2ne32(v)
+
+#ifndef HAVE_SWAB
+void swab(const void *from, void *to, ssize_t n);
+#endif
+
+#endif /* MPLAYER_MPBSWAP_H */
diff --git a/libavfilter/libmpcodecs/mpc_info.h b/libavfilter/libmpcodecs/mpc_info.h
new file mode 100644
index 0000000000..8554699120
--- /dev/null
+++ b/libavfilter/libmpcodecs/mpc_info.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_MPC_INFO_H
+#define MPLAYER_MPC_INFO_H
+
+typedef struct mp_codec_info_s
+{
+ /* codec long name ("Autodesk FLI/FLC Animation decoder" */
+ const char *name;
+ /* short name (same as driver name in codecs.conf) ("dshow") */
+ const char *short_name;
+ /* interface author/maintainer */
+ const char *maintainer;
+ /* codec author ("Aaron Holtzman <aholtzma@ess.engr.uvic.ca>") */
+ const char *author;
+ /* any additional comments */
+ const char *comment;
+} mp_codec_info_t;
+
+#define CONTROL_OK 1
+#define CONTROL_TRUE 1
+#define CONTROL_FALSE 0
+#define CONTROL_UNKNOWN -1
+#define CONTROL_ERROR -2
+#define CONTROL_NA -3
+
+#endif /* MPLAYER_MPC_INFO_H */
diff --git a/libavfilter/libmpcodecs/pullup.c b/libavfilter/libmpcodecs/pullup.c
new file mode 100644
index 0000000000..c1c4e0f5ca
--- /dev/null
+++ b/libavfilter/libmpcodecs/pullup.c
@@ -0,0 +1,822 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+#include "pullup.h"
+#include "cpudetect.h"
+
+
+
+#if ARCH_X86
+#if HAVE_MMX
+static int diff_y_mmx(unsigned char *a, unsigned char *b, int s)
+{
+ int ret;
+ __asm__ volatile (
+ "movl $4, %%ecx \n\t"
+ "pxor %%mm4, %%mm4 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+
+ "1: \n\t"
+
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "movq (%%"REG_D"), %%mm1 \n\t"
+ "add %%"REG_a", %%"REG_D" \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "psubusb %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm0, %%mm4 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz 1b \n\t"
+
+ "movq %%mm4, %%mm3 \n\t"
+ "punpcklwd %%mm7, %%mm4 \n\t"
+ "punpckhwd %%mm7, %%mm3 \n\t"
+ "paddd %%mm4, %%mm3 \n\t"
+ "movd %%mm3, %%eax \n\t"
+ "psrlq $32, %%mm3 \n\t"
+ "movd %%mm3, %%edx \n\t"
+ "addl %%edx, %%eax \n\t"
+ "emms \n\t"
+ : "=a" (ret)
+ : "S" (a), "D" (b), "a" (s)
+ : "%ecx", "%edx"
+ );
+ return ret;
+}
+
+static int licomb_y_mmx(unsigned char *a, unsigned char *b, int s)
+{
+ int ret;
+ __asm__ volatile (
+ "movl $4, %%ecx \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "sub %%"REG_a", %%"REG_D" \n\t"
+
+ "2: \n\t"
+
+ "movq (%%"REG_D"), %%mm0 \n\t"
+ "movq (%%"REG_D"), %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "movq (%%"REG_D",%%"REG_a"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm0, %%mm0 \n\t"
+ "paddw %%mm2, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "psubusw %%mm1, %%mm0 \n\t"
+ "psubusw %%mm2, %%mm1 \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+ "paddw %%mm1, %%mm6 \n\t"
+
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_D"), %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm0 \n\t"
+ "movq (%%"REG_D",%%"REG_a"), %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm0, %%mm0 \n\t"
+ "paddw %%mm2, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "psubusw %%mm1, %%mm0 \n\t"
+ "psubusw %%mm2, %%mm1 \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+ "paddw %%mm1, %%mm6 \n\t"
+
+ "movq (%%"REG_D",%%"REG_a"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "movq (%%"REG_S",%%"REG_a"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm0, %%mm0 \n\t"
+ "paddw %%mm2, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "psubusw %%mm1, %%mm0 \n\t"
+ "psubusw %%mm2, %%mm1 \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+ "paddw %%mm1, %%mm6 \n\t"
+
+ "movq (%%"REG_D",%%"REG_a"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm0 \n\t"
+ "movq (%%"REG_S",%%"REG_a"), %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm0, %%mm0 \n\t"
+ "paddw %%mm2, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "psubusw %%mm1, %%mm0 \n\t"
+ "psubusw %%mm2, %%mm1 \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+ "paddw %%mm1, %%mm6 \n\t"
+
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "add %%"REG_a", %%"REG_D" \n\t"
+ "decl %%ecx \n\t"
+ "jnz 2b \n\t"
+
+ "movq %%mm6, %%mm5 \n\t"
+ "punpcklwd %%mm7, %%mm6 \n\t"
+ "punpckhwd %%mm7, %%mm5 \n\t"
+ "paddd %%mm6, %%mm5 \n\t"
+ "movd %%mm5, %%eax \n\t"
+ "psrlq $32, %%mm5 \n\t"
+ "movd %%mm5, %%edx \n\t"
+ "addl %%edx, %%eax \n\t"
+
+ "emms \n\t"
+ : "=a" (ret)
+ : "S" (a), "D" (b), "a" (s)
+ : "%ecx", "%edx"
+ );
+ return ret;
+}
+
+static int var_y_mmx(unsigned char *a, unsigned char *b, int s)
+{
+ int ret;
+ __asm__ volatile (
+ "movl $3, %%ecx \n\t"
+ "pxor %%mm4, %%mm4 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+
+ "1: \n\t"
+
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+ "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "psubusb %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm0, %%mm4 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz 1b \n\t"
+
+ "movq %%mm4, %%mm3 \n\t"
+ "punpcklwd %%mm7, %%mm4 \n\t"
+ "punpckhwd %%mm7, %%mm3 \n\t"
+ "paddd %%mm4, %%mm3 \n\t"
+ "movd %%mm3, %%eax \n\t"
+ "psrlq $32, %%mm3 \n\t"
+ "movd %%mm3, %%edx \n\t"
+ "addl %%edx, %%eax \n\t"
+ "emms \n\t"
+ : "=a" (ret)
+ : "S" (a), "a" (s)
+ : "%ecx", "%edx"
+ );
+ return 4*ret;
+}
+#endif
+#endif
+
+#define ABS(a) (((a)^((a)>>31))-((a)>>31))
+
+static int diff_y(unsigned char *a, unsigned char *b, int s)
+{
+ int i, j, diff=0;
+ for (i=4; i; i--) {
+ for (j=0; j<8; j++) diff += ABS(a[j]-b[j]);
+ a+=s; b+=s;
+ }
+ return diff;
+}
+
+static int licomb_y(unsigned char *a, unsigned char *b, int s)
+{
+ int i, j, diff=0;
+ for (i=4; i; i--) {
+ for (j=0; j<8; j++)
+ diff += ABS((a[j]<<1) - b[j-s] - b[j])
+ + ABS((b[j]<<1) - a[j] - a[j+s]);
+ a+=s; b+=s;
+ }
+ return diff;
+}
+
+#if 0
+static int qpcomb_y(unsigned char *a, unsigned char *b, int s)
+{
+ int i, j, diff=0;
+ for (i=4; i; i--) {
+ for (j=0; j<8; j++)
+ diff += ABS(a[j] - 3*b[j-s] + 3*a[j+s] - b[j]);
+ a+=s; b+=s;
+ }
+ return diff;
+}
+
+static int licomb_y_test(unsigned char *a, unsigned char *b, int s)
+{
+ int c = licomb_y(a,b,s);
+ int m = licomb_y_mmx(a,b,s);
+ if (c != m) printf("%d != %d\n", c, m);
+ return m;
+}
+#endif
+
+static int var_y(unsigned char *a, unsigned char *b, int s)
+{
+ int i, j, var=0;
+ for (i=3; i; i--) {
+ for (j=0; j<8; j++) {
+ var += ABS(a[j]-a[j+s]);
+ }
+ a+=s; b+=s;
+ }
+ return 4*var; /* match comb scaling */
+}
+
+
+
+
+
+
+
+
+
+static void alloc_buffer(struct pullup_context *c, struct pullup_buffer *b)
+{
+ int i;
+ if (b->planes) return;
+ b->planes = calloc(c->nplanes, sizeof(unsigned char *));
+ for (i = 0; i < c->nplanes; i++) {
+ b->planes[i] = malloc(c->h[i]*c->stride[i]);
+ /* Deal with idiotic 128=0 for chroma: */
+ memset(b->planes[i], c->background[i], c->h[i]*c->stride[i]);
+ }
+}
+
+struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity)
+{
+ if (!b) return 0;
+ if ((parity+1) & 1) b->lock[0]++;
+ if ((parity+1) & 2) b->lock[1]++;
+ return b;
+}
+
+void pullup_release_buffer(struct pullup_buffer *b, int parity)
+{
+ if (!b) return;
+ if ((parity+1) & 1) b->lock[0]--;
+ if ((parity+1) & 2) b->lock[1]--;
+}
+
+struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity)
+{
+ int i;
+
+ /* Try first to get the sister buffer for the previous field */
+ if (parity < 2 && c->last && parity != c->last->parity
+ && !c->last->buffer->lock[parity]) {
+ alloc_buffer(c, c->last->buffer);
+ return pullup_lock_buffer(c->last->buffer, parity);
+ }
+
+ /* Prefer a buffer with both fields open */
+ for (i = 0; i < c->nbuffers; i++) {
+ if (c->buffers[i].lock[0]) continue;
+ if (c->buffers[i].lock[1]) continue;
+ alloc_buffer(c, &c->buffers[i]);
+ return pullup_lock_buffer(&c->buffers[i], parity);
+ }
+
+ if (parity == 2) return 0;
+
+ /* Search for any half-free buffer */
+ for (i = 0; i < c->nbuffers; i++) {
+ if (((parity+1) & 1) && c->buffers[i].lock[0]) continue;
+ if (((parity+1) & 2) && c->buffers[i].lock[1]) continue;
+ alloc_buffer(c, &c->buffers[i]);
+ return pullup_lock_buffer(&c->buffers[i], parity);
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+static void compute_metric(struct pullup_context *c,
+ struct pullup_field *fa, int pa,
+ struct pullup_field *fb, int pb,
+ int (*func)(unsigned char *, unsigned char *, int), int *dest)
+{
+ unsigned char *a, *b;
+ int x, y;
+ int mp = c->metric_plane;
+ int xstep = c->bpp[mp];
+ int ystep = c->stride[mp]<<3;
+ int s = c->stride[mp]<<1; /* field stride */
+ int w = c->metric_w*xstep;
+
+ if (!fa->buffer || !fb->buffer) return;
+
+ /* Shortcut for duplicate fields (e.g. from RFF flag) */
+ if (fa->buffer == fb->buffer && pa == pb) {
+ memset(dest, 0, c->metric_len * sizeof(int));
+ return;
+ }
+
+ a = fa->buffer->planes[mp] + pa * c->stride[mp] + c->metric_offset;
+ b = fb->buffer->planes[mp] + pb * c->stride[mp] + c->metric_offset;
+
+ for (y = c->metric_h; y; y--) {
+ for (x = 0; x < w; x += xstep) {
+ *dest++ = func(a + x, b + x, s);
+ }
+ a += ystep; b += ystep;
+ }
+}
+
+
+
+
+
+static void alloc_metrics(struct pullup_context *c, struct pullup_field *f)
+{
+ f->diffs = calloc(c->metric_len, sizeof(int));
+ f->comb = calloc(c->metric_len, sizeof(int));
+ f->var = calloc(c->metric_len, sizeof(int));
+ /* add more metrics here as needed */
+}
+
+static struct pullup_field *make_field_queue(struct pullup_context *c, int len)
+{
+ struct pullup_field *head, *f;
+ f = head = calloc(1, sizeof(struct pullup_field));
+ alloc_metrics(c, f);
+ for (; len > 0; len--) {
+ f->next = calloc(1, sizeof(struct pullup_field));
+ f->next->prev = f;
+ f = f->next;
+ alloc_metrics(c, f);
+ }
+ f->next = head;
+ head->prev = f;
+ return head;
+}
+
+static void check_field_queue(struct pullup_context *c)
+{
+ if (c->head->next == c->first) {
+ struct pullup_field *f = calloc(1, sizeof(struct pullup_field));
+ alloc_metrics(c, f);
+ f->prev = c->head;
+ f->next = c->first;
+ c->head->next = f;
+ c->first->prev = f;
+ }
+}
+
+void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity)
+{
+ struct pullup_field *f;
+
+ /* Grow the circular list if needed */
+ check_field_queue(c);
+
+ /* Cannot have two fields of same parity in a row; drop the new one */
+ if (c->last && c->last->parity == parity) return;
+
+ f = c->head;
+ f->parity = parity;
+ f->buffer = pullup_lock_buffer(b, parity);
+ f->flags = 0;
+ f->breaks = 0;
+ f->affinity = 0;
+
+ compute_metric(c, f, parity, f->prev->prev, parity, c->diff, f->diffs);
+ compute_metric(c, parity?f->prev:f, 0, parity?f:f->prev, 1, c->comb, f->comb);
+ compute_metric(c, f, parity, f, -1, c->var, f->var);
+
+ /* Advance the circular list */
+ if (!c->first) c->first = c->head;
+ c->last = c->head;
+ c->head = c->head->next;
+}
+
+void pullup_flush_fields(struct pullup_context *c)
+{
+ struct pullup_field *f;
+
+ for (f = c->first; f && f != c->head; f = f->next) {
+ pullup_release_buffer(f->buffer, f->parity);
+ f->buffer = 0;
+ }
+ c->first = c->last = 0;
+}
+
+
+
+
+
+
+
+
+#define F_HAVE_BREAKS 1
+#define F_HAVE_AFFINITY 2
+
+
+#define BREAK_LEFT 1
+#define BREAK_RIGHT 2
+
+
+
+
+static int queue_length(struct pullup_field *begin, struct pullup_field *end)
+{
+ int count = 1;
+ struct pullup_field *f;
+
+ if (!begin || !end) return 0;
+ for (f = begin; f != end; f = f->next) count++;
+ return count;
+}
+
+static int find_first_break(struct pullup_field *f, int max)
+{
+ int i;
+ for (i = 0; i < max; i++) {
+ if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT)
+ return i+1;
+ f = f->next;
+ }
+ return 0;
+}
+
+static void compute_breaks(struct pullup_context *c, struct pullup_field *f0)
+{
+ int i;
+ struct pullup_field *f1 = f0->next;
+ struct pullup_field *f2 = f1->next;
+ struct pullup_field *f3 = f2->next;
+ int l, max_l=0, max_r=0;
+ //struct pullup_field *ff;
+ //for (i=0, ff=c->first; ff != f0; i++, ff=ff->next);
+
+ if (f0->flags & F_HAVE_BREAKS) return;
+ //printf("\n%d: ", i);
+ f0->flags |= F_HAVE_BREAKS;
+
+ /* Special case when fields are 100% identical */
+ if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) {
+ f2->breaks |= BREAK_RIGHT;
+ return;
+ }
+ if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) {
+ f1->breaks |= BREAK_LEFT;
+ return;
+ }
+
+ for (i = 0; i < c->metric_len; i++) {
+ l = f2->diffs[i] - f3->diffs[i];
+ if (l > max_l) max_l = l;
+ if (-l > max_r) max_r = -l;
+ }
+ /* Don't get tripped up when differences are mostly quant error */
+ //printf("%d %d\n", max_l, max_r);
+ if (max_l + max_r < 128) return;
+ if (max_l > 4*max_r) f1->breaks |= BREAK_LEFT;
+ if (max_r > 4*max_l) f2->breaks |= BREAK_RIGHT;
+}
+
+static void compute_affinity(struct pullup_context *c, struct pullup_field *f)
+{
+ int i;
+ int max_l=0, max_r=0, l;
+ if (f->flags & F_HAVE_AFFINITY) return;
+ f->flags |= F_HAVE_AFFINITY;
+ if (f->buffer == f->next->next->buffer) {
+ f->affinity = 1;
+ f->next->affinity = 0;
+ f->next->next->affinity = -1;
+ f->next->flags |= F_HAVE_AFFINITY;
+ f->next->next->flags |= F_HAVE_AFFINITY;
+ return;
+ }
+ if (1) {
+ for (i = 0; i < c->metric_len; i++) {
+ int lv = f->prev->var[i];
+ int rv = f->next->var[i];
+ int v = f->var[i];
+ int lc = f->comb[i] - (v+lv) + ABS(v-lv);
+ int rc = f->next->comb[i] - (v+rv) + ABS(v-rv);
+ lc = lc>0 ? lc : 0;
+ rc = rc>0 ? rc : 0;
+ l = lc - rc;
+ if (l > max_l) max_l = l;
+ if (-l > max_r) max_r = -l;
+ }
+ if (max_l + max_r < 64) return;
+ if (max_r > 6*max_l) f->affinity = -1;
+ else if (max_l > 6*max_r) f->affinity = 1;
+ } else {
+ for (i = 0; i < c->metric_len; i++) {
+ l = f->comb[i] - f->next->comb[i];
+ if (l > max_l) max_l = l;
+ if (-l > max_r) max_r = -l;
+ }
+ if (max_l + max_r < 64) return;
+ if (max_r > 2*max_l) f->affinity = -1;
+ else if (max_l > 2*max_r) f->affinity = 1;
+ }
+}
+
+static void foo(struct pullup_context *c)
+{
+ struct pullup_field *f = c->first;
+ int i, n = queue_length(f, c->last);
+ for (i = 0; i < n-1; i++) {
+ if (i < n-3) compute_breaks(c, f);
+ compute_affinity(c, f);
+ f = f->next;
+ }
+}
+
+static int decide_frame_length(struct pullup_context *c)
+{
+ struct pullup_field *f0 = c->first;
+ struct pullup_field *f1 = f0->next;
+ struct pullup_field *f2 = f1->next;
+ int l;
+
+ if (queue_length(c->first, c->last) < 4) return 0;
+ foo(c);
+
+ if (f0->affinity == -1) return 1;
+
+ l = find_first_break(f0, 3);
+ if (l == 1 && c->strict_breaks < 0) l = 0;
+
+ switch (l) {
+ case 1:
+ if (c->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1)
+ return 2;
+ else return 1;
+ case 2:
+ /* FIXME: strictly speaking, f0->prev is no longer valid... :) */
+ if (c->strict_pairs
+ && (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT)
+ && (f0->affinity != 1 || f1->affinity != -1) )
+ return 1;
+ if (f1->affinity == 1) return 1;
+ else return 2;
+ case 3:
+ if (f2->affinity == 1) return 2;
+ else return 3;
+ default:
+ /* 9 possibilities covered before switch */
+ if (f1->affinity == 1) return 1; /* covers 6 */
+ else if (f1->affinity == -1) return 2; /* covers 6 */
+ else if (f2->affinity == -1) { /* covers 2 */
+ if (f0->affinity == 1) return 3;
+ else return 1;
+ }
+ else return 2; /* the remaining 6 */
+ }
+}
+
+
+static void print_aff_and_breaks(struct pullup_context *c, struct pullup_field *f)
+{
+ int i;
+ struct pullup_field *f0 = f;
+ const char aff_l[] = "+..", aff_r[] = "..+";
+ printf("\naffinity: ");
+ for (i = 0; i < 4; i++) {
+ printf("%c%d%c", aff_l[1+f->affinity], i, aff_r[1+f->affinity]);
+ f = f->next;
+ }
+ f = f0;
+ printf("\nbreaks: ");
+ for (i=0; i<4; i++) {
+ printf("%c%d%c", f->breaks & BREAK_LEFT ? '|' : '.', i, f->breaks & BREAK_RIGHT ? '|' : '.');
+ f = f->next;
+ }
+ printf("\n");
+}
+
+
+
+
+
+struct pullup_frame *pullup_get_frame(struct pullup_context *c)
+{
+ int i;
+ struct pullup_frame *fr = c->frame;
+ int n = decide_frame_length(c);
+ int aff = c->first->next->affinity;
+
+ if (!n) return 0;
+ if (fr->lock) return 0;
+
+ if (c->verbose) {
+ print_aff_and_breaks(c, c->first);
+ printf("duration: %d \n", n);
+ }
+
+ fr->lock++;
+ fr->length = n;
+ fr->parity = c->first->parity;
+ fr->buffer = 0;
+ for (i = 0; i < n; i++) {
+ /* We cheat and steal the buffer without release+relock */
+ fr->ifields[i] = c->first->buffer;
+ c->first->buffer = 0;
+ c->first = c->first->next;
+ }
+
+ if (n == 1) {
+ fr->ofields[fr->parity] = fr->ifields[0];
+ fr->ofields[fr->parity^1] = 0;
+ } else if (n == 2) {
+ fr->ofields[fr->parity] = fr->ifields[0];
+ fr->ofields[fr->parity^1] = fr->ifields[1];
+ } else if (n == 3) {
+ if (aff == 0)
+ aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
+ /* else if (c->verbose) printf("forced aff: %d \n", aff); */
+ fr->ofields[fr->parity] = fr->ifields[1+aff];
+ fr->ofields[fr->parity^1] = fr->ifields[1];
+ }
+ pullup_lock_buffer(fr->ofields[0], 0);
+ pullup_lock_buffer(fr->ofields[1], 1);
+
+ if (fr->ofields[0] == fr->ofields[1]) {
+ fr->buffer = fr->ofields[0];
+ pullup_lock_buffer(fr->buffer, 2);
+ return fr;
+ }
+ return fr;
+}
+
+static void copy_field(struct pullup_context *c, struct pullup_buffer *dest,
+ struct pullup_buffer *src, int parity)
+{
+ int i, j;
+ unsigned char *d, *s;
+ for (i = 0; i < c->nplanes; i++) {
+ s = src->planes[i] + parity*c->stride[i];
+ d = dest->planes[i] + parity*c->stride[i];
+ for (j = c->h[i]>>1; j; j--) {
+ memcpy(d, s, c->stride[i]);
+ s += c->stride[i]<<1;
+ d += c->stride[i]<<1;
+ }
+ }
+}
+
+void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr)
+{
+ int i;
+ if (fr->buffer) return;
+ if (fr->length < 2) return; /* FIXME: deal with this */
+ for (i = 0; i < 2; i++)
+ {
+ if (fr->ofields[i]->lock[i^1]) continue;
+ fr->buffer = fr->ofields[i];
+ pullup_lock_buffer(fr->buffer, 2);
+ copy_field(c, fr->buffer, fr->ofields[i^1], i^1);
+ return;
+ }
+ fr->buffer = pullup_get_buffer(c, 2);
+ copy_field(c, fr->buffer, fr->ofields[0], 0);
+ copy_field(c, fr->buffer, fr->ofields[1], 1);
+}
+
+void pullup_release_frame(struct pullup_frame *fr)
+{
+ int i;
+ for (i = 0; i < fr->length; i++)
+ pullup_release_buffer(fr->ifields[i], fr->parity ^ (i&1));
+ pullup_release_buffer(fr->ofields[0], 0);
+ pullup_release_buffer(fr->ofields[1], 1);
+ if (fr->buffer) pullup_release_buffer(fr->buffer, 2);
+ fr->lock--;
+}
+
+
+
+
+
+
+struct pullup_context *pullup_alloc_context(void)
+{
+ struct pullup_context *c;
+
+ c = calloc(1, sizeof(struct pullup_context));
+
+ return c;
+}
+
+void pullup_preinit_context(struct pullup_context *c)
+{
+ c->bpp = calloc(c->nplanes, sizeof(int));
+ c->w = calloc(c->nplanes, sizeof(int));
+ c->h = calloc(c->nplanes, sizeof(int));
+ c->stride = calloc(c->nplanes, sizeof(int));
+ c->background = calloc(c->nplanes, sizeof(int));
+}
+
+void pullup_init_context(struct pullup_context *c)
+{
+ int mp = c->metric_plane;
+ if (c->nbuffers < 10) c->nbuffers = 10;
+ c->buffers = calloc(c->nbuffers, sizeof (struct pullup_buffer));
+
+ c->metric_w = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3;
+ c->metric_h = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3;
+ c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp];
+ c->metric_len = c->metric_w * c->metric_h;
+
+ c->head = make_field_queue(c, 8);
+
+ c->frame = calloc(1, sizeof (struct pullup_frame));
+ c->frame->ifields = calloc(3, sizeof (struct pullup_buffer *));
+
+ switch(c->format) {
+ case PULLUP_FMT_Y:
+ c->diff = diff_y;
+ c->comb = licomb_y;
+ c->var = var_y;
+#if ARCH_X86
+#if HAVE_MMX
+ if (c->cpu & PULLUP_CPU_MMX) {
+ c->diff = diff_y_mmx;
+ c->comb = licomb_y_mmx;
+ c->var = var_y_mmx;
+ }
+#endif
+#endif
+ /* c->comb = qpcomb_y; */
+ break;
+#if 0
+ case PULLUP_FMT_YUY2:
+ c->diff = diff_yuy2;
+ break;
+ case PULLUP_FMT_RGB32:
+ c->diff = diff_rgb32;
+ break;
+#endif
+ }
+}
+
+void pullup_free_context(struct pullup_context *c)
+{
+ struct pullup_field *f;
+ free(c->buffers);
+ f = c->head;
+ do {
+ if (!f) break;
+ free(f->diffs);
+ free(f->comb);
+ f = f->next;
+ free(f->prev);
+ } while (f != c->head);
+ free(c->frame);
+ free(c);
+}
diff --git a/libavfilter/libmpcodecs/pullup.h b/libavfilter/libmpcodecs/pullup.h
new file mode 100644
index 0000000000..9c74fb5944
--- /dev/null
+++ b/libavfilter/libmpcodecs/pullup.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_PULLUP_H
+#define MPLAYER_PULLUP_H
+
+#define PULLUP_CPU_MMX 1
+#define PULLUP_CPU_MMX2 2
+#define PULLUP_CPU_3DNOW 4
+#define PULLUP_CPU_3DNOWEXT 8
+#define PULLUP_CPU_SSE 16
+#define PULLUP_CPU_SSE2 32
+
+#define PULLUP_FMT_Y 1
+#define PULLUP_FMT_YUY2 2
+#define PULLUP_FMT_UYVY 3
+#define PULLUP_FMT_RGB32 4
+
+struct pullup_buffer
+{
+ int lock[2];
+ unsigned char **planes;
+};
+
+struct pullup_field
+{
+ int parity;
+ struct pullup_buffer *buffer;
+ unsigned int flags;
+ int breaks;
+ int affinity;
+ int *diffs;
+ int *comb;
+ int *var;
+ struct pullup_field *prev, *next;
+};
+
+struct pullup_frame
+{
+ int lock;
+ int length;
+ int parity;
+ struct pullup_buffer **ifields, *ofields[2];
+ struct pullup_buffer *buffer;
+};
+
+struct pullup_context
+{
+ /* Public interface */
+ int format;
+ int nplanes;
+ int *bpp, *w, *h, *stride, *background;
+ unsigned int cpu;
+ int junk_left, junk_right, junk_top, junk_bottom;
+ int verbose;
+ int metric_plane;
+ int strict_breaks;
+ int strict_pairs;
+ /* Internal data */
+ struct pullup_field *first, *last, *head;
+ struct pullup_buffer *buffers;
+ int nbuffers;
+ int (*diff)(unsigned char *, unsigned char *, int);
+ int (*comb)(unsigned char *, unsigned char *, int);
+ int (*var)(unsigned char *, unsigned char *, int);
+ int metric_w, metric_h, metric_len, metric_offset;
+ struct pullup_frame *frame;
+};
+
+
+struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity);
+void pullup_release_buffer(struct pullup_buffer *b, int parity);
+struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity);
+
+void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity);
+void pullup_flush_fields(struct pullup_context *c);
+
+struct pullup_frame *pullup_get_frame(struct pullup_context *c);
+void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr);
+void pullup_release_frame(struct pullup_frame *fr);
+
+struct pullup_context *pullup_alloc_context(void);
+void pullup_preinit_context(struct pullup_context *c);
+void pullup_init_context(struct pullup_context *c);
+void pullup_free_context(struct pullup_context *c);
+
+#endif /* MPLAYER_PULLUP_H */
diff --git a/libavfilter/libmpcodecs/vd_ffmpeg.h b/libavfilter/libmpcodecs/vd_ffmpeg.h
new file mode 100644
index 0000000000..004d477330
--- /dev/null
+++ b/libavfilter/libmpcodecs/vd_ffmpeg.h
@@ -0,0 +1,24 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_VD_FFMPEG_H
+#define MPLAYER_VD_FFMPEG_H
+
+void init_avcodec(void);
+
+#endif /* MPLAYER_VD_FFMPEG_H */
diff --git a/libavfilter/libmpcodecs/vf.h b/libavfilter/libmpcodecs/vf.h
new file mode 100644
index 0000000000..3619e699f1
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf.h
@@ -0,0 +1,169 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_VF_H
+#define MPLAYER_VF_H
+
+#include "m_option.h"
+#include "mp_image.h"
+
+extern m_obj_settings_t* vf_settings;
+extern const m_obj_list_t vf_obj_list;
+
+struct vf_instance;
+struct vf_priv_s;
+
+typedef struct vf_info_s {
+ const char *info;
+ const char *name;
+ const char *author;
+ const char *comment;
+ int (*vf_open)(struct vf_instance *vf,char* args);
+ // Ptr to a struct dscribing the options
+ const void* opts;
+} vf_info_t;
+
+#define NUM_NUMBERED_MPI 50
+
+typedef struct vf_image_context_s {
+ mp_image_t* static_images[2];
+ mp_image_t* temp_images[1];
+ mp_image_t* export_images[1];
+ mp_image_t* numbered_images[NUM_NUMBERED_MPI];
+ int static_idx;
+} vf_image_context_t;
+
+typedef struct vf_format_context_t {
+ int have_configured;
+ int orig_width, orig_height, orig_fmt;
+} vf_format_context_t;
+
+typedef struct vf_instance {
+ const vf_info_t* info;
+ // funcs:
+ int (*config)(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt);
+ int (*control)(struct vf_instance *vf,
+ int request, void* data);
+ int (*query_format)(struct vf_instance *vf,
+ unsigned int fmt);
+ void (*get_image)(struct vf_instance *vf,
+ mp_image_t *mpi);
+ int (*put_image)(struct vf_instance *vf,
+ mp_image_t *mpi, double pts);
+ void (*start_slice)(struct vf_instance *vf,
+ mp_image_t *mpi);
+ void (*draw_slice)(struct vf_instance *vf,
+ unsigned char** src, int* stride, int w,int h, int x, int y);
+ void (*uninit)(struct vf_instance *vf);
+
+ int (*continue_buffered_image)(struct vf_instance *vf);
+ // caps:
+ unsigned int default_caps; // used by default query_format()
+ unsigned int default_reqs; // used by default config()
+ // data:
+ int w, h;
+ vf_image_context_t imgctx;
+ vf_format_context_t fmt;
+ struct vf_instance *next;
+ mp_image_t *dmpi;
+ struct vf_priv_s* priv;
+} vf_instance_t;
+
+// control codes:
+#include "mpc_info.h"
+
+typedef struct vf_seteq_s
+{
+ const char *item;
+ int value;
+} vf_equalizer_t;
+
+#define VFCTRL_QUERY_MAX_PP_LEVEL 4 /* test for postprocessing support (max level) */
+#define VFCTRL_SET_PP_LEVEL 5 /* set postprocessing level */
+#define VFCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
+#define VFCTRL_GET_EQUALIZER 8 /* gset color options (brightness,contrast etc) */
+#define VFCTRL_DRAW_OSD 7
+#define VFCTRL_CHANGE_RECTANGLE 9 /* Change the rectangle boundaries */
+#define VFCTRL_FLIP_PAGE 10 /* Tell the vo to flip pages */
+#define VFCTRL_DUPLICATE_FRAME 11 /* For encoding - encode zero-change frame */
+#define VFCTRL_SKIP_NEXT_FRAME 12 /* For encoding - drop the next frame that passes thru */
+#define VFCTRL_FLUSH_FRAMES 13 /* For encoding - flush delayed frames */
+#define VFCTRL_SCREENSHOT 14 /* Make a screenshot */
+#define VFCTRL_INIT_EOSD 15 /* Select EOSD renderer */
+#define VFCTRL_DRAW_EOSD 16 /* Render EOSD */
+#define VFCTRL_GET_PTS 17 /* Return last pts value that reached vf_vo*/
+#define VFCTRL_SET_DEINTERLACE 18 /* Set deinterlacing status */
+#define VFCTRL_GET_DEINTERLACE 19 /* Get deinterlacing status */
+
+#include "vfcap.h"
+
+//FIXME this should be in a common header, but i dunno which
+#define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly
+
+
+// functions:
+void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h);
+mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h);
+
+vf_instance_t* vf_open_plugin(const vf_info_t* const* filter_list, vf_instance_t* next, const char *name, char **args);
+vf_instance_t* vf_open_filter(vf_instance_t* next, const char *name, char **args);
+vf_instance_t* vf_add_before_vo(vf_instance_t **vf, char *name, char **args);
+vf_instance_t* vf_open_encoder(vf_instance_t* next, const char *name, char *args);
+
+unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred);
+void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src);
+void vf_queue_frame(vf_instance_t *vf, int (*)(vf_instance_t *));
+int vf_output_queued_frame(vf_instance_t *vf);
+
+// default wrappers:
+int vf_next_config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt);
+int vf_next_control(struct vf_instance *vf, int request, void* data);
+void vf_extra_flip(struct vf_instance *vf);
+int vf_next_query_format(struct vf_instance *vf, unsigned int fmt);
+int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts);
+void vf_next_draw_slice (struct vf_instance *vf, unsigned char** src, int* stride, int w,int h, int x, int y);
+
+vf_instance_t* append_filters(vf_instance_t* last);
+
+void vf_uninit_filter(vf_instance_t* vf);
+void vf_uninit_filter_chain(vf_instance_t* vf);
+
+int vf_config_wrapper(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt);
+
+static inline int norm_qscale(int qscale, int type)
+{
+ switch (type) {
+ case 0: // MPEG-1
+ return qscale;
+ case 1: // MPEG-2
+ return qscale >> 1;
+ case 2: // H264
+ return qscale >> 2;
+ case 3: // VP56
+ return (63 - qscale + 2) >> 2;
+ }
+ return qscale;
+}
+
+#endif /* MPLAYER_VF_H */
diff --git a/libavfilter/libmpcodecs/vf_2xsai.c b/libavfilter/libmpcodecs/vf_2xsai.c
new file mode 100644
index 0000000000..a19420ff98
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_2xsai.c
@@ -0,0 +1,336 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+//===========================================================================//
+
+/* FIXME: these all belong in the context, not as globals! */
+
+static uint32_t colorMask = 0xF7DEF7DE;
+static uint32_t lowPixelMask = 0x08210821;
+static uint32_t qcolorMask = 0xE79CE79C;
+static uint32_t qlowpixelMask = 0x18631863;
+static uint32_t redblueMask = 0xF81F;
+static uint32_t greenMask = 0x7E0;
+static int PixelsPerMask = 2;
+
+#define makecol(r,g,b) (r+(g<<8)+(b<<16))
+#define makecol_depth(d,r,g,b) (r+(g<<8)+(b<<16))
+
+static int Init_2xSaI(int d)
+{
+
+ int minr = 0, ming = 0, minb = 0;
+ int i;
+
+// if (d != 15 && d != 16 && d != 24 && d != 32)
+// return -1;
+
+ /* Get lowest color bit */
+ for (i = 0; i < 255; i++) {
+ if (!minr)
+ minr = makecol(i, 0, 0);
+ if (!ming)
+ ming = makecol(0, i, 0);
+ if (!minb)
+ minb = makecol(0, 0, i);
+ }
+
+ colorMask = (makecol_depth(d, 255, 0, 0) - minr) | (makecol_depth(d, 0, 255, 0) - ming) | (makecol_depth(d, 0, 0, 255) - minb);
+ lowPixelMask = minr | ming | minb;
+ qcolorMask = (makecol_depth(d, 255, 0, 0) - 3 * minr) | (makecol_depth(d, 0, 255, 0) - 3 * ming) | (makecol_depth(d, 0, 0, 255) - 3 * minb);
+ qlowpixelMask = (minr * 3) | (ming * 3) | (minb * 3);
+ redblueMask = makecol_depth(d, 255, 0, 255);
+ greenMask = makecol_depth(d, 0, 255, 0);
+
+ PixelsPerMask = (d <= 16) ? 2 : 1;
+
+ if (PixelsPerMask == 2) {
+ colorMask |= (colorMask << 16);
+ qcolorMask |= (qcolorMask << 16);
+ lowPixelMask |= (lowPixelMask << 16);
+ qlowpixelMask |= (qlowpixelMask << 16);
+ }
+
+// TRACE("Color Mask: 0x%lX\n", colorMask);
+// TRACE("Low Pixel Mask: 0x%lX\n", lowPixelMask);
+// TRACE("QColor Mask: 0x%lX\n", qcolorMask);
+// TRACE("QLow Pixel Mask: 0x%lX\n", qlowpixelMask);
+
+ return 0;
+}
+
+
+#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
+
+#define INTERPOLATE(A, B) (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask))
+
+#define Q_INTERPOLATE(A, B, C, D) ((A & qcolorMask) >> 2) + ((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2) \
+ + ((((A & qlowpixelMask) + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask)) >> 2) & qlowpixelMask)
+
+
+static void Super2xSaI_ex(uint8_t *src, uint32_t src_pitch,
+ uint8_t *dst, uint32_t dst_pitch,
+ uint32_t width, uint32_t height, int sbpp)
+{
+
+ unsigned int x, y;
+ uint32_t color[16];
+ unsigned char *src_line[4];
+
+ /* Point to the first 3 lines. */
+ src_line[0] = src;
+ src_line[1] = src;
+ src_line[2] = src + src_pitch;
+ src_line[3] = src + src_pitch * 2;
+
+ x = 0, y = 0;
+
+ if (PixelsPerMask == 2) {
+ unsigned short *sbp;
+ sbp = (unsigned short*)src_line[0];
+ color[0] = *sbp; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
+ color[4] = color[0]; color[5] = color[0]; color[6] = *(sbp + 1); color[7] = *(sbp + 2);
+ sbp = (unsigned short*)src_line[2];
+ color[8] = *sbp; color[9] = color[8]; color[10] = *(sbp + 1); color[11] = *(sbp + 2);
+ sbp = (unsigned short*)src_line[3];
+ color[12] = *sbp; color[13] = color[12]; color[14] = *(sbp + 1); color[15] = *(sbp + 2);
+ }
+ else {
+ uint32_t *lbp;
+ lbp = (uint32_t*)src_line[0];
+ color[0] = *lbp; color[1] = color[0]; color[2] = color[0]; color[3] = color[0];
+ color[4] = color[0]; color[5] = color[0]; color[6] = *(lbp + 1); color[7] = *(lbp + 2);
+ lbp = (uint32_t*)src_line[2];
+ color[8] = *lbp; color[9] = color[8]; color[10] = *(lbp + 1); color[11] = *(lbp + 2);
+ lbp = (uint32_t*)src_line[3];
+ color[12] = *lbp; color[13] = color[12]; color[14] = *(lbp + 1); color[15] = *(lbp + 2);
+ }
+
+ for (y = 0; y < height; y++) {
+ unsigned char *dst_line[2];
+
+ dst_line[0] = dst + dst_pitch*2*y;
+ dst_line[1] = dst + dst_pitch*(2*y+1);
+
+ /* Todo: x = width - 2, x = width - 1 */
+
+ for (x = 0; x < width; x++) {
+ uint32_t product1a, product1b, product2a, product2b;
+
+//--------------------------------------- B0 B1 B2 B3 0 1 2 3
+// 4 5* 6 S2 -> 4 5* 6 7
+// 1 2 3 S1 8 9 10 11
+// A0 A1 A2 A3 12 13 14 15
+//--------------------------------------
+ if (color[9] == color[6] && color[5] != color[10]) {
+ product2b = color[9];
+ product1b = product2b;
+ }
+ else if (color[5] == color[10] && color[9] != color[6]) {
+ product2b = color[5];
+ product1b = product2b;
+ }
+ else if (color[5] == color[10] && color[9] == color[6]) {
+ int r = 0;
+
+ r += GET_RESULT(color[6], color[5], color[8], color[13]);
+ r += GET_RESULT(color[6], color[5], color[4], color[1]);
+ r += GET_RESULT(color[6], color[5], color[14], color[11]);
+ r += GET_RESULT(color[6], color[5], color[2], color[7]);
+
+ if (r > 0)
+ product1b = color[6];
+ else if (r < 0)
+ product1b = color[5];
+ else
+ product1b = INTERPOLATE(color[5], color[6]);
+
+ product2b = product1b;
+
+ }
+ else {
+ if (color[6] == color[10] && color[10] == color[13] && color[9] != color[14] && color[10] != color[12])
+ product2b = Q_INTERPOLATE(color[10], color[10], color[10], color[9]);
+ else if (color[5] == color[9] && color[9] == color[14] && color[13] != color[10] && color[9] != color[15])
+ product2b = Q_INTERPOLATE(color[9], color[9], color[9], color[10]);
+ else
+ product2b = INTERPOLATE(color[9], color[10]);
+
+ if (color[6] == color[10] && color[6] == color[1] && color[5] != color[2] && color[6] != color[0])
+ product1b = Q_INTERPOLATE(color[6], color[6], color[6], color[5]);
+ else if (color[5] == color[9] && color[5] == color[2] && color[1] != color[6] && color[5] != color[3])
+ product1b = Q_INTERPOLATE(color[6], color[5], color[5], color[5]);
+ else
+ product1b = INTERPOLATE(color[5], color[6]);
+ }
+
+ if (color[5] == color[10] && color[9] != color[6] && color[4] == color[5] && color[5] != color[14])
+ product2a = INTERPOLATE(color[9], color[5]);
+ else if (color[5] == color[8] && color[6] == color[5] && color[4] != color[9] && color[5] != color[12])
+ product2a = INTERPOLATE(color[9], color[5]);
+ else
+ product2a = color[9];
+
+ if (color[9] == color[6] && color[5] != color[10] && color[8] == color[9] && color[9] != color[2])
+ product1a = INTERPOLATE(color[9], color[5]);
+ else if (color[4] == color[9] && color[10] == color[9] && color[8] != color[5] && color[9] != color[0])
+ product1a = INTERPOLATE(color[9], color[5]);
+ else
+ product1a = color[5];
+
+ if (PixelsPerMask == 2) {
+ *((uint32_t *) (&dst_line[0][x * 4])) = product1a | (product1b << 16);
+ *((uint32_t *) (&dst_line[1][x * 4])) = product2a | (product2b << 16);
+ }
+ else {
+ *((uint32_t *) (&dst_line[0][x * 8])) = product1a;
+ *((uint32_t *) (&dst_line[0][x * 8 + 4])) = product1b;
+ *((uint32_t *) (&dst_line[1][x * 8])) = product2a;
+ *((uint32_t *) (&dst_line[1][x * 8 + 4])) = product2b;
+ }
+
+ /* Move color matrix forward */
+ color[0] = color[1]; color[4] = color[5]; color[8] = color[9]; color[12] = color[13];
+ color[1] = color[2]; color[5] = color[6]; color[9] = color[10]; color[13] = color[14];
+ color[2] = color[3]; color[6] = color[7]; color[10] = color[11]; color[14] = color[15];
+
+ if (x < width - 3) {
+ x += 3;
+ if (PixelsPerMask == 2) {
+ color[3] = *(((unsigned short*)src_line[0]) + x);
+ color[7] = *(((unsigned short*)src_line[1]) + x);
+ color[11] = *(((unsigned short*)src_line[2]) + x);
+ color[15] = *(((unsigned short*)src_line[3]) + x);
+ }
+ else {
+ color[3] = *(((uint32_t*)src_line[0]) + x);
+ color[7] = *(((uint32_t*)src_line[1]) + x);
+ color[11] = *(((uint32_t*)src_line[2]) + x);
+ color[15] = *(((uint32_t*)src_line[3]) + x);
+ }
+ x -= 3;
+ }
+ }
+
+ /* We're done with one line, so we shift the source lines up */
+ src_line[0] = src_line[1];
+ src_line[1] = src_line[2];
+ src_line[2] = src_line[3];
+
+ /* Read next line */
+ if (y + 3 >= height)
+ src_line[3] = src_line[2];
+ else
+ src_line[3] = src_line[2] + src_pitch;
+
+ /* Then shift the color matrix up */
+ if (PixelsPerMask == 2) {
+ unsigned short *sbp;
+ sbp = (unsigned short*)src_line[0];
+ color[0] = *sbp; color[1] = color[0]; color[2] = *(sbp + 1); color[3] = *(sbp + 2);
+ sbp = (unsigned short*)src_line[1];
+ color[4] = *sbp; color[5] = color[4]; color[6] = *(sbp + 1); color[7] = *(sbp + 2);
+ sbp = (unsigned short*)src_line[2];
+ color[8] = *sbp; color[9] = color[9]; color[10] = *(sbp + 1); color[11] = *(sbp + 2);
+ sbp = (unsigned short*)src_line[3];
+ color[12] = *sbp; color[13] = color[12]; color[14] = *(sbp + 1); color[15] = *(sbp + 2);
+ }
+ else {
+ uint32_t *lbp;
+ lbp = (uint32_t*)src_line[0];
+ color[0] = *lbp; color[1] = color[0]; color[2] = *(lbp + 1); color[3] = *(lbp + 2);
+ lbp = (uint32_t*)src_line[1];
+ color[4] = *lbp; color[5] = color[4]; color[6] = *(lbp + 1); color[7] = *(lbp + 2);
+ lbp = (uint32_t*)src_line[2];
+ color[8] = *lbp; color[9] = color[9]; color[10] = *(lbp + 1); color[11] = *(lbp + 2);
+ lbp = (uint32_t*)src_line[3];
+ color[12] = *lbp; color[13] = color[12]; color[14] = *(lbp + 1); color[15] = *(lbp + 2);
+ }
+
+ } // y loop
+
+}
+
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ Init_2xSaI(outfmt&255);
+
+ return vf_next_config(vf,2*width,2*height,2*d_width,2*d_height,flags,outfmt);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ 2*mpi->w, 2*mpi->h);
+
+ Super2xSaI_ex(mpi->planes[0], mpi->stride[0],
+ dmpi->planes[0], dmpi->stride[0],
+ mpi->w, mpi->h, mpi->bpp/8);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt){
+// case IMGFMT_BGR15:
+// case IMGFMT_BGR16:
+ case IMGFMT_BGR32:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ return 1;
+}
+
+const vf_info_t vf_info_2xsai = {
+ "2xSai BGR bitmap 2x scaler",
+ "2xsai",
+ "A'rpi",
+ "http://elektron.its.tudelft.nl/~dalikifa/",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_blackframe.c b/libavfilter/libmpcodecs/vf_blackframe.c
new file mode 100644
index 0000000000..c72552c99e
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_blackframe.c
@@ -0,0 +1,148 @@
+/*
+ * detect frames that are (almost) black
+ * search for black frames to detect scene transitions
+ * (c) 2006 Julian Hall
+ *
+ * based on code designed for skipping commercials
+ * (c) 2002-2003 Brian J. Murrell
+ *
+ * cleanup, simplify, speedup (c) 2006 by Ivo van Poorten
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ unsigned int bamount, bthresh, frame, lastkeyframe;
+};
+
+static int config(struct vf_instance *vf, int width, int height, int d_width,
+ int d_height, unsigned int flags, unsigned int outfmt) {
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static int query_format(struct vf_instance *vf, unsigned fmt) {
+ switch(fmt) {
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_NV12:
+ case IMGFMT_NV21:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ case IMGFMT_HM12:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ int x, y;
+ int nblack=0, pblack=0;
+ unsigned char *yplane = mpi->planes[0];
+ unsigned int ystride = mpi->stride[0];
+ int pict_type = mpi->pict_type;
+ int w = mpi->w, h = mpi->h;
+ int bthresh = vf->priv->bthresh;
+ int bamount = vf->priv->bamount;
+ static const char *const picttypes[4] = { "unknown", "I", "P", "B" };
+
+ for (y=1; y<=h; y++) {
+ for (x=0; x<w; x++)
+ nblack += yplane[x] < bthresh;
+ pblack = nblack*100/(w*y);
+ if (pblack < bamount) break;
+ yplane += ystride;
+ }
+
+ if (pict_type > 3 || pict_type < 0) pict_type = 0;
+ if (pict_type == 1) vf->priv->lastkeyframe = vf->priv->frame;
+
+ if (pblack >= bamount)
+ mp_msg(MSGT_VFILTER, MSGL_INFO,"vf_blackframe: %u, %i%%, %s (I:%u)\n",
+ vf->priv->frame, pblack, picttypes[pict_type],
+ vf->priv->lastkeyframe);
+
+ vf->priv->frame++;
+
+ dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, 0,
+ mpi->width, mpi->height);
+ dmpi->planes[0] = mpi->planes[0];
+ dmpi->stride[0] = mpi->stride[0];
+ dmpi->planes[1] = mpi->planes[1];
+ dmpi->stride[1] = mpi->stride[1];
+ dmpi->planes[2] = mpi->planes[2];
+ dmpi->stride[2] = mpi->stride[2];
+
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ return vf_next_put_image(vf, dmpi, pts);
+}
+
+static int control(struct vf_instance *vf, int request, void* data){
+ return vf_next_control(vf,request,data);
+}
+
+static void uninit(struct vf_instance *vf) {
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->priv = malloc(sizeof(struct vf_priv_s));
+ if (!vf->priv) return 0;
+
+ vf->config = config;
+ vf->put_image = put_image;
+ vf->control = control;
+ vf->uninit = uninit;
+ vf->query_format = query_format;
+
+ vf->priv->bamount = 98;
+ vf->priv->bthresh = 0x20;
+ vf->priv->frame = 0;
+ vf->priv->lastkeyframe = 0;
+
+ if (args)
+ sscanf(args, "%u:%u", &vf->priv->bamount, &vf->priv->bthresh);
+ return 1;
+}
+
+const vf_info_t vf_info_blackframe = {
+ "detects black frames",
+ "blackframe",
+ "Brian J. Murrell, Julian Hall, Ivo van Poorten",
+ "Useful for detecting scene transitions",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_boxblur.c b/libavfilter/libmpcodecs/vf_boxblur.c
new file mode 100644
index 0000000000..bc1ec80284
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_boxblur.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "mp_msg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+
+//===========================================================================//
+
+typedef struct FilterParam{
+ int radius;
+ int power;
+}FilterParam;
+
+struct vf_priv_s {
+ FilterParam lumaParam;
+ FilterParam chromaParam;
+};
+
+
+/***************************************************************************/
+
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static inline void blur(uint8_t *dst, uint8_t *src, int w, int radius, int dstStep, int srcStep){
+ int x;
+ const int length= radius*2 + 1;
+ const int inv= ((1<<16) + length/2)/length;
+
+ int sum= 0;
+
+ for(x=0; x<radius; x++){
+ sum+= src[x*srcStep]<<1;
+ }
+ sum+= src[radius*srcStep];
+
+ for(x=0; x<=radius; x++){
+ sum+= src[(radius+x)*srcStep] - src[(radius-x)*srcStep];
+ dst[x*dstStep]= (sum*inv + (1<<15))>>16;
+ }
+
+ for(; x<w-radius; x++){
+ sum+= src[(radius+x)*srcStep] - src[(x-radius-1)*srcStep];
+ dst[x*dstStep]= (sum*inv + (1<<15))>>16;
+ }
+
+ for(; x<w; x++){
+ sum+= src[(2*w-radius-x-1)*srcStep] - src[(x-radius-1)*srcStep];
+ dst[x*dstStep]= (sum*inv + (1<<15))>>16;
+ }
+}
+
+static inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int power, int dstStep, int srcStep){
+ uint8_t temp[2][4096];
+ uint8_t *a= temp[0], *b=temp[1];
+
+ if(radius){
+ blur(a, src, w, radius, 1, srcStep);
+ for(; power>2; power--){
+ uint8_t *c;
+ blur(b, a, w, radius, 1, 1);
+ c=a; a=b; b=c;
+ }
+ if(power>1)
+ blur(dst, a, w, radius, dstStep, 1);
+ else{
+ int i;
+ for(i=0; i<w; i++)
+ dst[i*dstStep]= a[i];
+ }
+ }else{
+ int i;
+ for(i=0; i<w; i++)
+ dst[i*dstStep]= src[i*srcStep];
+ }
+}
+
+static void hBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){
+ int y;
+
+ if(radius==0 && dst==src) return;
+
+ for(y=0; y<h; y++){
+ blur2(dst + y*dstStride, src + y*srcStride, w, radius, power, 1, 1);
+ }
+}
+
+//FIXME optimize (x before y !!!)
+static void vBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){
+ int x;
+
+ if(radius==0 && dst==src) return;
+
+ for(x=0; x<w; x++){
+ blur2(dst + x, src + x, h, radius, power, dstStride, srcStride);
+ }
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+
+ mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_READABLE,
+ mpi->w,mpi->h);
+
+ assert(mpi->flags&MP_IMGFLAG_PLANAR);
+
+ hBlur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h,
+ dmpi->stride[0], mpi->stride[0], vf->priv->lumaParam.radius, vf->priv->lumaParam.power);
+ hBlur(dmpi->planes[1], mpi->planes[1], cw,ch,
+ dmpi->stride[1], mpi->stride[1], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
+ hBlur(dmpi->planes[2], mpi->planes[2], cw,ch,
+ dmpi->stride[2], mpi->stride[2], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
+
+ vBlur(dmpi->planes[0], dmpi->planes[0], mpi->w,mpi->h,
+ dmpi->stride[0], dmpi->stride[0], vf->priv->lumaParam.radius, vf->priv->lumaParam.power);
+ vBlur(dmpi->planes[1], dmpi->planes[1], cw,ch,
+ dmpi->stride[1], dmpi->stride[1], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
+ vBlur(dmpi->planes[2], dmpi->planes[2], cw,ch,
+ dmpi->stride[2], dmpi->stride[2], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ int e;
+
+ vf->config=config;
+ vf->put_image=put_image;
+// vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if(args==NULL) return 0;
+
+ e=sscanf(args, "%d:%d:%d:%d",
+ &vf->priv->lumaParam.radius,
+ &vf->priv->lumaParam.power,
+ &vf->priv->chromaParam.radius,
+ &vf->priv->chromaParam.power
+ );
+
+ if(e==2){
+ vf->priv->chromaParam.radius= vf->priv->lumaParam.radius;
+ vf->priv->chromaParam.power = vf->priv->lumaParam.power;
+ }else if(e!=4)
+ return 0;
+
+ if(vf->priv->lumaParam.radius < 0) return 0;
+ if(vf->priv->chromaParam.radius < 0) return 0;
+
+ return 1;
+}
+
+const vf_info_t vf_info_boxblur = {
+ "box blur",
+ "boxblur",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_cropdetect.c b/libavfilter/libmpcodecs/vf_cropdetect.c
new file mode 100644
index 0000000000..c3de24793b
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_cropdetect.c
@@ -0,0 +1,201 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ int x1,y1,x2,y2;
+ int limit;
+ int round;
+ int reset_count;
+ int fno;
+};
+
+static int checkline(unsigned char* src,int stride,int len,int bpp){
+ int total=0;
+ int div=len;
+ switch(bpp){
+ case 1:
+ while(--len>=0){
+ total+=src[0]; src+=stride;
+ }
+ break;
+ case 3:
+ case 4:
+ while(--len>=0){
+ total+=src[0]+src[1]+src[2]; src+=stride;
+ }
+ div*=3;
+ break;
+ }
+ total/=div;
+// printf("total=%d\n",total);
+ return total;
+}
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ vf->priv->x1=width - 1;
+ vf->priv->y1=height - 1;
+ vf->priv->x2=0;
+ vf->priv->y2=0;
+ vf->priv->fno=-2;
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ int bpp=mpi->bpp/8;
+ int w,h,x,y,shrink_by;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, 0,
+ mpi->w, mpi->h);
+
+ dmpi->planes[0]=mpi->planes[0];
+ dmpi->planes[1]=mpi->planes[1];
+ dmpi->planes[2]=mpi->planes[2];
+ dmpi->stride[0]=mpi->stride[0];
+ dmpi->stride[1]=mpi->stride[1];
+ dmpi->stride[2]=mpi->stride[2];
+ dmpi->width=mpi->width;
+ dmpi->height=mpi->height;
+
+if(++vf->priv->fno>0){ // ignore first 2 frames - they may be empty
+
+ // Reset the crop area every reset_count frames, if reset_count is > 0
+ if(vf->priv->reset_count > 0 && vf->priv->fno > vf->priv->reset_count){
+ vf->priv->x1=mpi->w-1;
+ vf->priv->y1=mpi->h-1;
+ vf->priv->x2=0;
+ vf->priv->y2=0;
+ vf->priv->fno=1;
+ }
+
+ for(y=0;y<vf->priv->y1;y++){
+ if(checkline(mpi->planes[0]+mpi->stride[0]*y,bpp,mpi->w,bpp)>vf->priv->limit){
+ vf->priv->y1=y;
+ break;
+ }
+ }
+
+ for(y=mpi->h-1;y>vf->priv->y2;y--){
+ if(checkline(mpi->planes[0]+mpi->stride[0]*y,bpp,mpi->w,bpp)>vf->priv->limit){
+ vf->priv->y2=y;
+ break;
+ }
+ }
+
+ for(y=0;y<vf->priv->x1;y++){
+ if(checkline(mpi->planes[0]+bpp*y,mpi->stride[0],mpi->h,bpp)>vf->priv->limit){
+ vf->priv->x1=y;
+ break;
+ }
+ }
+
+ for(y=mpi->w-1;y>vf->priv->x2;y--){
+ if(checkline(mpi->planes[0]+bpp*y,mpi->stride[0],mpi->h,bpp)>vf->priv->limit){
+ vf->priv->x2=y;
+ break;
+ }
+ }
+
+ // round x and y (up), important for yuv colorspaces
+ // make sure they stay rounded!
+ x=(vf->priv->x1+1)&(~1);
+ y=(vf->priv->y1+1)&(~1);
+
+ w = vf->priv->x2 - x + 1;
+ h = vf->priv->y2 - y + 1;
+
+ // w and h must be divisible by 2 as well because of yuv
+ // colorspace problems.
+ if (vf->priv->round <= 1)
+ vf->priv->round = 16;
+ if (vf->priv->round % 2)
+ vf->priv->round *= 2;
+
+ shrink_by = w % vf->priv->round;
+ w -= shrink_by;
+ x += (shrink_by / 2 + 1) & ~1;
+
+ shrink_by = h % vf->priv->round;
+ h -= shrink_by;
+ y += (shrink_by / 2 + 1) & ~1;
+
+ mp_msg(MSGT_VFILTER, MSGL_INFO, MSGTR_MPCODECS_CropArea,
+ vf->priv->x1,vf->priv->x2,
+ vf->priv->y1,vf->priv->y2,
+ w,h,x,y);
+
+
+}
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt) {
+ switch(fmt) {
+ // the default limit value works only right with YV12 right now.
+ case IMGFMT_YV12:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+//===========================================================================//
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ vf->priv->limit=24; // should be option
+ vf->priv->round = 0;
+ vf->priv->reset_count = 0;
+ if(args) sscanf(args, "%d:%d:%d",
+ &vf->priv->limit,
+ &vf->priv->round,
+ &vf->priv->reset_count);
+ return 1;
+}
+
+const vf_info_t vf_info_cropdetect = {
+ "autodetect crop size",
+ "cropdetect",
+ "A'rpi",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_decimate.c b/libavfilter/libmpcodecs/vf_decimate.c
new file mode 100644
index 0000000000..1fd7bce3d3
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_decimate.c
@@ -0,0 +1,198 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+
+struct vf_priv_s {
+ int hi, lo;
+ float frac;
+ int max, last, cnt;
+};
+
+#if HAVE_MMX && HAVE_EBX_AVAILABLE
+static int diff_MMX(unsigned char *old, unsigned char *new, int os, int ns)
+{
+ volatile short out[4];
+ __asm__ (
+ "movl $8, %%ecx \n\t"
+ "pxor %%mm4, %%mm4 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+
+ ASMALIGN(4)
+ "1: \n\t"
+
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "movq (%%"REG_D"), %%mm1 \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "psubusb %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm0, %%mm4 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz 1b \n\t"
+ "movq %%mm4, (%%"REG_d") \n\t"
+ "emms \n\t"
+ :
+ : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out)
+ : "%ecx", "memory"
+ );
+ return out[0]+out[1]+out[2]+out[3];
+}
+#endif
+
+static int diff_C(unsigned char *old, unsigned char *new, int os, int ns)
+{
+ int x, y, d=0;
+ for (y = 8; y; y--) {
+ for (x = 8; x; x--) {
+ d += abs(new[x] - old[x]);
+ }
+ new += ns;
+ old += os;
+ }
+ return d;
+}
+
+static int (*diff)(unsigned char *, unsigned char *, int, int);
+
+static int diff_to_drop_plane(int hi, int lo, float frac, unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
+{
+ int x, y;
+ int d, c=0;
+ int t = (w/16)*(h/16)*frac;
+ for (y = 0; y < h-7; y += 4) {
+ for (x = 8; x < w-7; x += 4) {
+ d = diff(old+x+y*os, new+x+y*ns, os, ns);
+ if (d > hi) return 0;
+ if (d > lo) {
+ c++;
+ if (c > t) return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+static int diff_to_drop(int hi, int lo, float frac, mp_image_t *old, mp_image_t *new)
+{
+ if (new->flags & MP_IMGFLAG_PLANAR) {
+ return diff_to_drop_plane(hi,lo,frac, old->planes[0], new->planes[0],
+ new->w, new->h, old->stride[0], new->stride[0])
+ && diff_to_drop_plane(hi,lo,frac, old->planes[1], new->planes[1],
+ new->chroma_width, new->chroma_height,
+ old->stride[1], new->stride[1])
+ && diff_to_drop_plane(hi,lo,frac, old->planes[2], new->planes[2],
+ new->chroma_width, new->chroma_height,
+ old->stride[2], new->stride[2]);
+ }
+ return diff_to_drop_plane(hi,lo,frac, old->planes[0], new->planes[0],
+ new->w*(new->bpp/8), new->h, old->stride[0], new->stride[0]);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
+ mpi->width, mpi->height);
+ dmpi->qscale = mpi->qscale;
+ dmpi->qstride = mpi->qstride;
+ dmpi->qscale_type = mpi->qscale_type;
+
+ if (diff_to_drop(vf->priv->hi, vf->priv->lo, vf->priv->frac, dmpi, mpi)) {
+ if (vf->priv->max == 0)
+ return 0;
+ else if ((vf->priv->max > 0) && (vf->priv->cnt++ < vf->priv->max))
+ return 0;
+ else if ((vf->priv->max < 0) && (vf->priv->last+1 >= -vf->priv->max))
+ return vf->priv->last=0;
+ }
+ vf->priv->last++;
+ vf->priv->cnt=0;
+
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0], mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2], mpi->stride[2]);
+ }
+ return vf_next_put_image(vf, dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ vf->put_image = put_image;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ p->max = 0;
+ p->hi = 64*12;
+ p->lo = 64*5;
+ p->frac = 0.33;
+ if (args) sscanf(args, "%d:%d:%d:%f", &p->max, &p->hi, &p->lo, &p->frac);
+ diff = diff_C;
+#if HAVE_MMX && HAVE_EBX_AVAILABLE
+ if(gCpuCaps.hasMMX) diff = diff_MMX;
+#endif
+ return 1;
+}
+
+const vf_info_t vf_info_decimate = {
+ "near-duplicate frame remover",
+ "decimate",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_delogo.c b/libavfilter/libmpcodecs/vf_delogo.c
new file mode 100644
index 0000000000..fb85c553ab
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_delogo.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2002 Jindrich Makovicka <makovick@gmail.com>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* A very simple tv station logo remover */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+
+#include "m_option.h"
+#include "m_struct.h"
+
+//===========================================================================//
+
+static struct vf_priv_s {
+ unsigned int outfmt;
+ int xoff, yoff, lw, lh, band, show;
+} const vf_priv_dflt = {
+ 0,
+ 0, 0, 0, 0, 0, 0
+};
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+
+static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height,
+ int logo_x, int logo_y, int logo_w, int logo_h, int band, int show, int direct) {
+ int y, x;
+ int interp, dist;
+ uint8_t *xdst, *xsrc;
+
+ uint8_t *topleft, *botleft, *topright;
+ int xclipl, xclipr, yclipt, yclipb;
+ int logo_x1, logo_x2, logo_y1, logo_y2;
+
+ xclipl = MAX(-logo_x, 0);
+ xclipr = MAX(logo_x+logo_w-width, 0);
+ yclipt = MAX(-logo_y, 0);
+ yclipb = MAX(logo_y+logo_h-height, 0);
+
+ logo_x1 = logo_x + xclipl;
+ logo_x2 = logo_x + logo_w - xclipr;
+ logo_y1 = logo_y + yclipt;
+ logo_y2 = logo_y + logo_h - yclipb;
+
+ topleft = src+logo_y1*srcStride+logo_x1;
+ topright = src+logo_y1*srcStride+logo_x2-1;
+ botleft = src+(logo_y2-1)*srcStride+logo_x1;
+
+ if (!direct) memcpy_pic(dst, src, width, height, dstStride, srcStride);
+
+ dst += (logo_y1+1)*dstStride;
+ src += (logo_y1+1)*srcStride;
+
+ for(y = logo_y1+1; y < logo_y2-1; y++)
+ {
+ for (x = logo_x1+1, xdst = dst+logo_x1+1, xsrc = src+logo_x1+1; x < logo_x2-1; x++, xdst++, xsrc++) {
+ interp = ((topleft[srcStride*(y-logo_y-yclipt)]
+ + topleft[srcStride*(y-logo_y-1-yclipt)]
+ + topleft[srcStride*(y-logo_y+1-yclipt)])*(logo_w-(x-logo_x))/logo_w
+ + (topright[srcStride*(y-logo_y-yclipt)]
+ + topright[srcStride*(y-logo_y-1-yclipt)]
+ + topright[srcStride*(y-logo_y+1-yclipt)])*(x-logo_x)/logo_w
+ + (topleft[x-logo_x-xclipl]
+ + topleft[x-logo_x-1-xclipl]
+ + topleft[x-logo_x+1-xclipl])*(logo_h-(y-logo_y))/logo_h
+ + (botleft[x-logo_x-xclipl]
+ + botleft[x-logo_x-1-xclipl]
+ + botleft[x-logo_x+1-xclipl])*(y-logo_y)/logo_h
+ )/6;
+/* interp = (topleft[srcStride*(y-logo_y)]*(logo_w-(x-logo_x))/logo_w
+ + topright[srcStride*(y-logo_y)]*(x-logo_x)/logo_w
+ + topleft[x-logo_x]*(logo_h-(y-logo_y))/logo_h
+ + botleft[x-logo_x]*(y-logo_y)/logo_h
+ )/2;*/
+ if (y >= logo_y+band && y < logo_y+logo_h-band && x >= logo_x+band && x < logo_x+logo_w-band) {
+ *xdst = interp;
+ } else {
+ dist = 0;
+ if (x < logo_x+band) dist = MAX(dist, logo_x-x+band);
+ else if (x >= logo_x+logo_w-band) dist = MAX(dist, x-(logo_x+logo_w-1-band));
+ if (y < logo_y+band) dist = MAX(dist, logo_y-y+band);
+ else if (y >= logo_y+logo_h-band) dist = MAX(dist, y-(logo_y+logo_h-1-band));
+ *xdst = (*xsrc*dist + interp*(band-dist))/band;
+ if (show && (dist == band-1)) *xdst = 0;
+ }
+ }
+
+ dst+= dstStride;
+ src+= srcStride;
+ }
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags, mpi->w, mpi->h);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+ }
+ dmpi= vf->dmpi;
+
+ delogo(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h,
+ vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show,
+ mpi->flags&MP_IMGFLAG_DIRECT);
+ delogo(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2,
+ vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
+ mpi->flags&MP_IMGFLAG_DIRECT);
+ delogo(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2,
+ vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
+ mpi->flags&MP_IMGFLAG_DIRECT);
+
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ return vf_next_query_format(vf,vf->priv->outfmt);
+ }
+ return 0;
+}
+
+static const unsigned int fmt_list[]={
+ IMGFMT_YV12,
+ IMGFMT_I420,
+ IMGFMT_IYUV,
+ 0
+};
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+
+ mp_msg(MSGT_VFILTER, MSGL_V, "delogo: %d x %d, %d x %d, band = %d\n",
+ vf->priv->xoff, vf->priv->yoff,
+ vf->priv->lw, vf->priv->lh,
+ vf->priv->band);
+
+ vf->priv->show = 0;
+
+ if (vf->priv->band < 0) {
+ vf->priv->band = 4;
+ vf->priv->show = 1;
+ }
+
+
+ vf->priv->lw += vf->priv->band*2;
+ vf->priv->lh += vf->priv->band*2;
+ vf->priv->xoff -= vf->priv->band;
+ vf->priv->yoff -= vf->priv->band;
+
+ // check csp:
+ vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
+ if(!vf->priv->outfmt)
+ {
+ uninit(vf);
+ return 0; // no csp match :(
+ }
+
+ return 1;
+}
+
+#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
+static const m_option_t vf_opts_fields[] = {
+ { "x", ST_OFF(xoff), CONF_TYPE_INT, 0, 0, 0, NULL },
+ { "y", ST_OFF(yoff), CONF_TYPE_INT, 0, 0, 0, NULL },
+ { "w", ST_OFF(lw), CONF_TYPE_INT, 0, 0, 0, NULL },
+ { "h", ST_OFF(lh), CONF_TYPE_INT, 0, 0, 0, NULL },
+ { "t", ST_OFF(band), CONF_TYPE_INT, 0, 0, 0, NULL },
+ { "band", ST_OFF(band), CONF_TYPE_INT, 0, 0, 0, NULL }, // alias
+ { NULL, NULL, 0, 0, 0, 0, NULL }
+};
+
+static const m_struct_t vf_opts = {
+ "delogo",
+ sizeof(struct vf_priv_s),
+ &vf_priv_dflt,
+ vf_opts_fields
+};
+
+const vf_info_t vf_info_delogo = {
+ "simple logo remover",
+ "delogo",
+ "Jindrich Makovicka, Alex Beregszaszi",
+ "",
+ vf_open,
+ &vf_opts
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_denoise3d.c b/libavfilter/libmpcodecs/vf_denoise3d.c
new file mode 100644
index 0000000000..a952a22287
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_denoise3d.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "mp_msg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#define PARAM1_DEFAULT 4.0
+#define PARAM2_DEFAULT 3.0
+#define PARAM3_DEFAULT 6.0
+
+//===========================================================================//
+
+struct vf_priv_s {
+ int Coefs[4][512];
+ unsigned char *Line;
+ mp_image_t *pmpi;
+};
+
+
+/***************************************************************************/
+
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ free(vf->priv->Line);
+ vf->priv->Line = malloc(width);
+ vf->priv->pmpi=NULL;
+// vf->default_caps &= !VFCAP_ACCEPT_STRIDE;
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv->Line);
+}
+
+#define LowPass(Prev, Curr, Coef) (Curr + Coef[Prev - Curr])
+
+static void deNoise(unsigned char *Frame, // mpi->planes[x]
+ unsigned char *FramePrev, // pmpi->planes[x]
+ unsigned char *FrameDest, // dmpi->planes[x]
+ unsigned char *LineAnt, // vf->priv->Line (width bytes)
+ int W, int H, int sStride, int pStride, int dStride,
+ int *Horizontal, int *Vertical, int *Temporal)
+{
+ int X, Y;
+ int sLineOffs = 0, pLineOffs = 0, dLineOffs = 0;
+ unsigned char PixelAnt;
+
+ /* First pixel has no left nor top neighbor. Only previous frame */
+ LineAnt[0] = PixelAnt = Frame[0];
+ FrameDest[0] = LowPass(FramePrev[0], LineAnt[0], Temporal);
+
+ /* Fist line has no top neighbor. Only left one for each pixel and
+ * last frame */
+ for (X = 1; X < W; X++)
+ {
+ PixelAnt = LowPass(PixelAnt, Frame[X], Horizontal);
+ LineAnt[X] = PixelAnt;
+ FrameDest[X] = LowPass(FramePrev[X], LineAnt[X], Temporal);
+ }
+
+ for (Y = 1; Y < H; Y++)
+ {
+ sLineOffs += sStride, pLineOffs += pStride, dLineOffs += dStride;
+ /* First pixel on each line doesn't have previous pixel */
+ PixelAnt = Frame[sLineOffs];
+ LineAnt[0] = LowPass(LineAnt[0], PixelAnt, Vertical);
+ FrameDest[dLineOffs] = LowPass(FramePrev[pLineOffs], LineAnt[0], Temporal);
+
+ for (X = 1; X < W; X++)
+ {
+ /* The rest are normal */
+ PixelAnt = LowPass(PixelAnt, Frame[sLineOffs+X], Horizontal);
+ LineAnt[X] = LowPass(LineAnt[X], PixelAnt, Vertical);
+ FrameDest[dLineOffs+X] = LowPass(FramePrev[pLineOffs+X], LineAnt[X], Temporal);
+ }
+ }
+}
+
+
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+ int W = mpi->w, H = mpi->h;
+
+ mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
+ mpi->w,mpi->h);
+
+ if(!dmpi) return 0;
+ if (!vf->priv->pmpi) vf->priv->pmpi=mpi;
+
+ deNoise(mpi->planes[0], vf->priv->pmpi->planes[0], dmpi->planes[0],
+ vf->priv->Line, W, H,
+ mpi->stride[0], vf->priv->pmpi->stride[0], dmpi->stride[0],
+ vf->priv->Coefs[0] + 256,
+ vf->priv->Coefs[0] + 256,
+ vf->priv->Coefs[1] + 256);
+ deNoise(mpi->planes[1], vf->priv->pmpi->planes[1], dmpi->planes[1],
+ vf->priv->Line, cw, ch,
+ mpi->stride[1], vf->priv->pmpi->stride[1], dmpi->stride[1],
+ vf->priv->Coefs[2] + 256,
+ vf->priv->Coefs[2] + 256,
+ vf->priv->Coefs[3] + 256);
+ deNoise(mpi->planes[2], vf->priv->pmpi->planes[2], dmpi->planes[2],
+ vf->priv->Line, cw, ch,
+ mpi->stride[2], vf->priv->pmpi->stride[2], dmpi->stride[2],
+ vf->priv->Coefs[2] + 256,
+ vf->priv->Coefs[2] + 256,
+ vf->priv->Coefs[3] + 256);
+
+ vf->priv->pmpi=dmpi; // save reference image
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+
+#define ABS(A) ( (A) > 0 ? (A) : -(A) )
+
+static void PrecalcCoefs(int *Ct, double Dist25)
+{
+ int i;
+ double Gamma, Simil, C;
+
+ Gamma = log(0.25) / log(1.0 - Dist25/255.0);
+
+ for (i = -256; i <= 255; i++)
+ {
+ Simil = 1.0 - ABS(i) / 255.0;
+// Ct[256+i] = lround(pow(Simil, Gamma) * (double)i);
+ C = pow(Simil, Gamma) * (double)i;
+ Ct[256+i] = (C<0) ? (C-0.5) : (C+0.5);
+ }
+}
+
+
+static int vf_open(vf_instance_t *vf, char *args){
+ double LumSpac, LumTmp, ChromSpac, ChromTmp;
+ double Param1, Param2, Param3;
+
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if (args)
+ {
+ switch(sscanf(args, "%lf:%lf:%lf",
+ &Param1, &Param2, &Param3
+ ))
+ {
+ case 0:
+ LumSpac = PARAM1_DEFAULT;
+ LumTmp = PARAM3_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ case 1:
+ LumSpac = Param1;
+ LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ case 2:
+ LumSpac = Param1;
+ LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
+
+ ChromSpac = Param2;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ case 3:
+ LumSpac = Param1;
+ LumTmp = Param3;
+
+ ChromSpac = Param2;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ default:
+ LumSpac = PARAM1_DEFAULT;
+ LumTmp = PARAM3_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ }
+ }
+ else
+ {
+ LumSpac = PARAM1_DEFAULT;
+ LumTmp = PARAM3_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ }
+
+ PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
+ PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
+ PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
+ PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
+
+ return 1;
+}
+
+const vf_info_t vf_info_denoise3d = {
+ "3D Denoiser (variable lowpass filter)",
+ "denoise3d",
+ "Daniel Moreno",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_detc.c b/libavfilter/libmpcodecs/vf_detc.c
new file mode 100644
index 0000000000..8122233de2
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_detc.c
@@ -0,0 +1,453 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+struct metrics {
+ int even;
+ int odd;
+ int noise;
+ int temp;
+};
+
+struct vf_priv_s {
+ int frame;
+ int drop, lastdrop;
+ struct metrics pm;
+ int thres[5];
+ int inframes, outframes;
+ int mode;
+ int (*analyze)(struct vf_priv_s *, mp_image_t *, mp_image_t *);
+ int needread;
+};
+
+#define COMPE(a,b,e) (abs((a)-(b)) < (((a)+(b))>>(e)))
+#define COMPARABLE(a,b) COMPE((a),(b),2)
+#define VERYCLOSE(a,b) COMPE((a),(b),3)
+
+#define OUTER_TC_NBHD(s) ( \
+ COMPARABLE((s)[-1].m.even,(s)[-1].m.odd) && \
+ COMPARABLE((s)[1].m.even,(s)[0].m.odd) && \
+ COMPARABLE((s)[2].m.even,(s)[1].m.odd) && \
+ COMPARABLE((s)[-1].m.noise,(s)[0].m.temp) && \
+ COMPARABLE((s)[2].m.noise,(s)[2].m.temp) )
+
+#define INNER_TC_NBHD(s,l,h) ( \
+ COMPARABLE((s)[0].m.even,(l)) && \
+ COMPARABLE((s)[2].m.odd,(l)) && ( \
+ COMPARABLE((s)[0].m.noise,(h)) || \
+ COMPARABLE((s)[1].m.noise,(h)) ) )
+
+enum {
+ TC_DROP,
+ TC_PROG,
+ TC_IL1,
+ TC_IL2
+};
+
+static void block_diffs(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
+{
+ int x, y, even=0, odd=0, noise, temp;
+ unsigned char *oldp, *newp;
+ m->noise = m->temp = 0;
+ for (x = 8; x; x--) {
+ oldp = old++;
+ newp = new++;
+ noise = temp = 0;
+ for (y = 4; y; y--) {
+ even += abs(newp[0]-oldp[0]);
+ odd += abs(newp[ns]-oldp[os]);
+ noise += newp[ns]-newp[0];
+ temp += oldp[os]-newp[0];
+ oldp += os<<1;
+ newp += ns<<1;
+ }
+ m->noise += abs(noise);
+ m->temp += abs(temp);
+ }
+ m->even = even;
+ m->odd = odd;
+}
+
+static void diff_planes(struct metrics *m, unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
+{
+ int x, y, me=0, mo=0, mn=0, mt=0;
+ struct metrics l;
+ for (y = 0; y < h-7; y += 8) {
+ for (x = 0; x < w-7; x += 8) {
+ block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns);
+ if (l.even > me) me = l.even;
+ if (l.odd > mo) mo = l.odd;
+ if (l.noise > mn) mn = l.noise;
+ if (l.temp > mt) mt = l.temp;
+ }
+ }
+ m->even = me;
+ m->odd = mo;
+ m->noise = mn;
+ m->temp = mt;
+}
+
+static void diff_fields(struct metrics *metr, mp_image_t *old, mp_image_t *new)
+{
+ struct metrics m, mu, mv;
+ diff_planes(&m, old->planes[0], new->planes[0],
+ new->w, new->h, old->stride[0], new->stride[0]);
+ if (new->flags & MP_IMGFLAG_PLANAR) {
+ diff_planes(&mu, old->planes[1], new->planes[1],
+ new->chroma_width, new->chroma_height,
+ old->stride[1], new->stride[1]);
+ diff_planes(&mv, old->planes[2], new->planes[2],
+ new->chroma_width, new->chroma_height,
+ old->stride[2], new->stride[2]);
+ if (mu.even > m.even) m.even = mu.even;
+ if (mu.odd > m.odd) m.odd = mu.odd;
+ if (mu.noise > m.noise) m.noise = mu.noise;
+ if (mu.temp > m.temp) m.temp = mu.temp;
+ if (mv.even > m.even) m.even = mv.even;
+ if (mv.odd > m.odd) m.odd = mv.odd;
+ if (mv.noise > m.noise) m.noise = mv.noise;
+ if (mv.temp > m.temp) m.temp = mv.temp;
+ }
+ *metr = m;
+}
+
+static void status(int f, struct metrics *m)
+{
+ mp_msg(MSGT_VFILTER, MSGL_V, "frame %d: e=%d o=%d n=%d t=%d\n",
+ f, m->even, m->odd, m->noise, m->temp);
+}
+
+static int analyze_fixed_pattern(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old)
+{
+ if (p->frame >= 0) p->frame = (p->frame+1)%5;
+ mp_msg(MSGT_VFILTER, MSGL_V, "frame %d\n", p->frame);
+ switch (p->frame) {
+ case -1: case 0: case 1: case 2:
+ return TC_PROG;
+ case 3:
+ return TC_IL1;
+ case 4:
+ return TC_IL2;
+ }
+ return 0;
+}
+
+static int analyze_aggressive(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old)
+{
+ struct metrics m, pm;
+
+ if (p->frame >= 0) p->frame = (p->frame+1)%5;
+
+ diff_fields(&m, old, new);
+
+ status(p->frame, &m);
+
+ pm = p->pm;
+ p->pm = m;
+
+ if (p->frame == 4) {
+ /* We need to break at scene changes, but is this a valid test? */
+ if ((m.even > p->thres[2]) && (m.odd > p->thres[2]) && (m.temp > p->thres[3])
+ && (m.temp > 5*pm.temp) && (m.temp*2 > m.noise)) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "scene change breaking telecine!\n");
+ p->frame = -1;
+ return TC_DROP;
+ }
+ /* Thres. is to compensate for quantization errors when noise is low */
+ if (m.noise - m.temp > -p->thres[4]) {
+ if (COMPARABLE(m.even, pm.odd)) {
+ //mp_msg(MSGT_VFILTER, MSGL_V, "confirmed field match!\n");
+ return TC_IL2;
+ } else if ((m.even < p->thres[0]) && (m.odd < p->thres[0]) && VERYCLOSE(m.even, m.odd)
+ && VERYCLOSE(m.noise,m.temp) && VERYCLOSE(m.noise,pm.noise)) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "interlaced frame appears in duplicate!!!\n");
+ p->pm = pm; /* hack :) */
+ p->frame = 3;
+ return TC_IL1;
+ }
+ } else {
+ mp_msg(MSGT_VFILTER, MSGL_V, "mismatched telecine fields!\n");
+ p->frame = -1;
+ }
+ }
+
+ if (2*m.even*m.temp < m.odd*m.noise) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "caught telecine sync!\n");
+ p->frame = 3;
+ return TC_IL1;
+ }
+
+ if (p->frame < 3) {
+ if (m.noise > p->thres[3]) {
+ if (m.noise > 2*m.temp) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "merging fields out of sequence!\n");
+ return TC_IL2;
+ }
+ if ((m.noise > 2*pm.noise) && (m.even > p->thres[2]) && (m.odd > p->thres[2])) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "dropping horrible interlaced frame!\n");
+ return TC_DROP;
+ }
+ }
+ }
+
+ switch (p->frame) {
+ case -1:
+ if (4*m.noise > 5*m.temp) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "merging fields out of sequence!\n");
+ return TC_IL2;
+ }
+ case 0:
+ case 1:
+ case 2:
+ return TC_PROG;
+ case 3:
+ if ((m.even > p->thres[1]) && (m.even > m.odd) && (m.temp > m.noise)) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "lost telecine tracking!\n");
+ p->frame = -1;
+ return TC_PROG;
+ }
+ return TC_IL1;
+ case 4:
+ return TC_IL2;
+ }
+ return 0;
+}
+
+static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field)
+{
+ switch (field) {
+ case 0:
+ my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ break;
+ case 1:
+ my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
+ mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
+ mpi->planes[1]+mpi->stride[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
+ mpi->planes[2]+mpi->stride[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ break;
+ case 2:
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0], mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2], mpi->stride[2]);
+ }
+ break;
+ }
+}
+
+static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi)
+{
+ struct vf_priv_s *p = vf->priv;
+ int dropflag;
+
+ switch (p->drop) {
+ default:
+ dropflag = 0;
+ break;
+ case 1:
+ dropflag = (++p->lastdrop >= 5);
+ break;
+ case 2:
+ dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes);
+ break;
+ }
+
+ if (dropflag) {
+ mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n",
+ p->outframes, p->inframes, (float)p->outframes/p->inframes);
+ p->lastdrop = 0;
+ return 0;
+ }
+
+ p->outframes++;
+ return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ int ret=0;
+ mp_image_t *dmpi;
+ struct vf_priv_s *p = vf->priv;
+
+ p->inframes++;
+
+ if (p->needread) dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
+ mpi->width, mpi->height);
+ /* FIXME: is there a good way to get rid of static type? */
+ else dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
+
+ switch (p->analyze(p, mpi, dmpi)) {
+ case TC_DROP:
+ /* Don't copy anything unless we'll need to read it. */
+ if (p->needread) copy_image(dmpi, mpi, 2);
+ p->lastdrop = 0;
+ break;
+ case TC_PROG:
+ /* Copy and display the whole frame. */
+ copy_image(dmpi, mpi, 2);
+ ret = do_put_image(vf, dmpi);
+ break;
+ case TC_IL1:
+ /* Only copy bottom field unless we need to read. */
+ if (p->needread) copy_image(dmpi, mpi, 2);
+ else copy_image(dmpi, mpi, 1);
+ p->lastdrop = 0;
+ break;
+ case TC_IL2:
+ /* Copy top field and show frame, then copy bottom if needed. */
+ copy_image(dmpi, mpi, 0);
+ ret = do_put_image(vf, dmpi);
+ if (p->needread) copy_image(dmpi, mpi, 1);
+ break;
+ }
+ return ret;
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - figure out which other formats work */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static struct {
+ char *name;
+ int (*func)(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old);
+ int needread;
+} anal_funcs[] = {
+ { "fixed", analyze_fixed_pattern, 0 },
+ { "aggressive", analyze_aggressive, 1 },
+ { NULL, NULL, 0 }
+};
+
+#define STARTVARS if (0)
+#define GETVAR(str, name, out, func) \
+ else if (!strncmp((str), name "=", sizeof(name))) \
+ (out) = (func)((str) + sizeof(name))
+
+static void parse_var(struct vf_priv_s *p, char *var)
+{
+ STARTVARS;
+ GETVAR(var, "dr", p->drop, atoi);
+ GETVAR(var, "t0", p->thres[0], atoi);
+ GETVAR(var, "t1", p->thres[1], atoi);
+ GETVAR(var, "t2", p->thres[2], atoi);
+ GETVAR(var, "t3", p->thres[3], atoi);
+ GETVAR(var, "t4", p->thres[4], atoi);
+ GETVAR(var, "fr", p->frame, atoi);
+ GETVAR(var, "am", p->mode, atoi);
+}
+
+static void parse_args(struct vf_priv_s *p, char *args)
+{
+ char *next, *orig;
+ for (args=orig=strdup(args); args; args=next) {
+ next = strchr(args, ':');
+ if (next) *next++ = 0;
+ parse_var(p, args);
+ }
+ free(orig);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ vf->config = config;
+ vf->put_image = put_image;
+ vf->query_format = query_format;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ p->frame = -1;
+ p->thres[0] = 440;
+ p->thres[1] = 720;
+ p->thres[2] = 2500;
+ p->thres[3] = 2500;
+ p->thres[4] = 800;
+ p->drop = 0;
+ p->mode = 1;
+ if (args) parse_args(p, args);
+ p->analyze = anal_funcs[p->mode].func;
+ p->needread = anal_funcs[p->mode].needread;
+ return 1;
+}
+
+const vf_info_t vf_info_detc = {
+ "de-telecine filter",
+ "detc",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_dint.c b/libavfilter/libmpcodecs/vf_dint.c
new file mode 100644
index 0000000000..7038381221
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_dint.c
@@ -0,0 +1,214 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "mp_image.h"
+#include "img_format.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ float sense; // first parameter
+ float level; // second parameter
+ unsigned int imgfmt;
+ char diff;
+ uint32_t max;
+// int dfr;
+// int rdfr;
+ int was_dint;
+ mp_image_t *pmpi; // previous mpi
+};
+
+#define MAXROWSIZE 1200
+
+static int config (struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ int rowsize;
+
+ vf->priv->pmpi = vf_get_image (vf->next, outfmt, MP_IMGTYPE_TEMP,
+ 0, width, height);
+ if (!(vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) &&
+ outfmt != IMGFMT_RGB32 && outfmt != IMGFMT_BGR32 &&
+ outfmt != IMGFMT_RGB24 && outfmt != IMGFMT_BGR24 &&
+ outfmt != IMGFMT_RGB16 && outfmt != IMGFMT_BGR16)
+ {
+ mp_msg (MSGT_VFILTER, MSGL_WARN, "Drop-interlaced filter doesn't support this outfmt :(\n");
+ return 0;
+ }
+ vf->priv->imgfmt = outfmt;
+ // recalculate internal values
+ rowsize = vf->priv->pmpi->width;
+ if (rowsize > MAXROWSIZE) rowsize = MAXROWSIZE;
+ vf->priv->max = vf->priv->level * vf->priv->pmpi->height * rowsize / 2;
+ if (vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) // planar YUV
+ vf->priv->diff = vf->priv->sense * 256;
+ else
+ vf->priv->diff = vf->priv->sense * (1 << (vf->priv->pmpi->bpp/3));
+ if (vf->priv->diff < 0) vf->priv->diff = 0;
+ if (!(vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) &&
+ vf->priv->pmpi->bpp < 24 && vf->priv->diff > 31)
+ vf->priv->diff = 31;
+ mp_msg (MSGT_VFILTER, MSGL_INFO, "Drop-interlaced: %dx%d diff %d / level %u\n",
+ vf->priv->pmpi->width, vf->priv->pmpi->height,
+ (int)vf->priv->diff, (unsigned int)vf->priv->max);
+// vf->priv->rdfr = vf->priv->dfr = 0;
+ vf->priv->was_dint = 0;
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static int put_image (struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ char rrow0[MAXROWSIZE];
+ char rrow1[MAXROWSIZE];
+ char rrow2[MAXROWSIZE];
+ char *row0 = rrow0, *row1 = rrow1, *row2 = rrow2/*, *row3 = rrow3*/;
+ int rowsize = mpi->width;
+ uint32_t nok = 0, max = vf->priv->max;
+ int diff = vf->priv->diff;
+ int i, j;
+ register int n1, n2;
+ unsigned char *cur0, *prv0;
+ register unsigned char *cur, *prv;
+
+ if (rowsize > MAXROWSIZE) rowsize = MAXROWSIZE;
+ // check if nothing to do
+ if (mpi->imgfmt == vf->priv->imgfmt)
+ {
+ cur0 = mpi->planes[0] + mpi->stride[0];
+ prv0 = mpi->planes[0];
+ for (j = 1; j < mpi->height && nok <= max; j++)
+ {
+ cur = cur0;
+ prv = prv0;
+ // analyse row (row0)
+ if (mpi->flags & MP_IMGFLAG_PLANAR) // planar YUV - check luminance
+ for (i = 0; i < rowsize; i++)
+ {
+ if (cur[0] - prv[0] > diff)
+ row0[i] = 1;
+ else if (cur[0] - prv[0] < -diff)
+ row0[i] = -1;
+ else
+ row0[i] = 0;
+ cur++;
+ prv++;
+ // check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
+ // but row3 is 1 so it's interlaced ptr (nok++)
+ if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
+ (++nok) > max)
+ break;
+ }
+ else if (mpi->bpp < 24) // RGB/BGR 16 - check all colors
+ for (i = 0; i < rowsize; i++)
+ {
+ n1 = cur[0] + (cur[1]<<8);
+ n2 = prv[0] + (prv[1]<<8);
+ if ((n1&0x1f) - (n2&0x1f) > diff ||
+ ((n1>>5)&0x3f) - ((n2>>5)&0x3f) > diff ||
+ ((n1>>11)&0x1f) - ((n2>>11)&0x1f) > diff)
+ row0[i] = 1;
+ else if ((n1&0x1f) - (n2&0x1f) < -diff ||
+ ((n1>>5)&0x3f) - ((n2>>5)&0x3f) < -diff ||
+ ((n1>>11)&0x1f) - ((n2>>11)&0x1f) < -diff)
+ row0[i] = -1;
+ else
+ row0[i] = 0;
+ cur += 2;
+ prv += 2;
+ // check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
+ // but row3 is 1 so it's interlaced ptr (nok++)
+ if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
+ (++nok) > max)
+ break;
+ }
+ else // RGB/BGR 24/32
+ for (i = 0; i < rowsize; i++)
+ {
+ if (cur[0] - prv[0] > diff ||
+ cur[1] - prv[1] > diff ||
+ cur[2] - prv[2] > diff)
+ row0[i] = 1;
+ else if (prv[0] - cur[0] > diff ||
+ prv[1] - cur[1] > diff ||
+ prv[2] - cur[2] > diff)
+ row0[i] = -1;
+ else
+ row0[i] = 0;
+ cur += mpi->bpp/8;
+ prv += mpi->bpp/8;
+ // check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
+ // but row3 is 1 so it's interlaced ptr (nok++)
+ if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
+ (++nok) > max)
+ break;
+ }
+ cur0 += mpi->stride[0];
+ prv0 += mpi->stride[0];
+ // rotate rows
+ cur = row2;
+ row2 = row1;
+ row1 = row0;
+ row0 = cur;
+ }
+ }
+ // check if number of interlaced is above of max
+ if (nok > max)
+ {
+// vf->priv->dfr++;
+ if (vf->priv->was_dint < 1) // can skip at most one frame!
+ {
+ vf->priv->was_dint++;
+// vf->priv->rdfr++;
+// mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
+ return 0;
+ }
+ }
+ vf->priv->was_dint = 0;
+// mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
+ return vf_next_put_image (vf, mpi, pts);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config = config;
+ vf->put_image = put_image;
+// vf->default_reqs=VFCAP_ACCEPT_STRIDE;
+ vf->priv = malloc (sizeof(struct vf_priv_s));
+ vf->priv->sense = 0.1;
+ vf->priv->level = 0.15;
+ vf->priv->pmpi = NULL;
+ if (args)
+ sscanf (args, "%f:%f", &vf->priv->sense, &vf->priv->level);
+ return 1;
+}
+
+const vf_info_t vf_info_dint = {
+ "drop interlaced frames",
+ "dint",
+ "A.G.",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_divtc.c b/libavfilter/libmpcodecs/vf_divtc.c
new file mode 100644
index 0000000000..5cc9932feb
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_divtc.c
@@ -0,0 +1,720 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+#include "libavutil/common.h"
+#include "mpbswap.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+const vf_info_t vf_info_divtc;
+
+struct vf_priv_s
+ {
+ int deghost, pass, phase, window, fcount, bcount, frameno, misscount,
+ ocount, sum[5];
+ double threshold;
+ FILE *file;
+ char *bdata;
+ unsigned int *csdata;
+ int *history;
+ };
+
+/*
+ * diff_MMX and diff_C stolen from vf_decimate.c
+ */
+
+#if HAVE_MMX && HAVE_EBX_AVAILABLE
+static int diff_MMX(unsigned char *old, unsigned char *new, int os, int ns)
+ {
+ volatile short out[4];
+ __asm__ (
+ "movl $8, %%ecx \n\t"
+ "pxor %%mm4, %%mm4 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+
+ ASMALIGN(4)
+ "1: \n\t"
+
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "movq (%%"REG_D"), %%mm1 \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "psubusb %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm0, %%mm4 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz 1b \n\t"
+ "movq %%mm4, (%%"REG_d") \n\t"
+ "emms \n\t"
+ :
+ : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out)
+ : "%ecx", "memory"
+ );
+ return out[0]+out[1]+out[2]+out[3];
+ }
+#endif
+
+static int diff_C(unsigned char *old, unsigned char *new, int os, int ns)
+ {
+ int x, y, d=0;
+
+ for(y=8; y; y--, new+=ns, old+=os)
+ for(x=8; x; x--)
+ d+=abs(new[x]-old[x]);
+
+ return d;
+ }
+
+static int (*diff)(unsigned char *, unsigned char *, int, int);
+
+static int diff_plane(unsigned char *old, unsigned char *new,
+ int w, int h, int os, int ns, int arg)
+ {
+ int x, y, d, max=0, sum=0, n=0;
+
+ for(y=0; y<h-7; y+=8)
+ {
+ for(x=0; x<w-7; x+=8)
+ {
+ d=diff(old+x+y*os, new+x+y*ns, os, ns);
+ if(d>max) max=d;
+ sum+=d;
+ n++;
+ }
+ }
+
+ return (sum+n*max)/2;
+ }
+
+/*
+static unsigned int checksum_plane(unsigned char *p, unsigned char *z,
+ int w, int h, int s, int zs, int arg)
+ {
+ unsigned int shift, sum;
+ unsigned char *e;
+
+ for(sum=0; h; h--, p+=s-w)
+ for(e=p+w, shift=32; p<e;)
+ sum^=(*p++)<<(shift=(shift-8)&31);
+
+ return sum;
+ }
+*/
+
+static unsigned int checksum_plane(unsigned char *p, unsigned char *z,
+ int w, int h, int s, int zs, int arg)
+ {
+ unsigned int shift;
+ uint32_t sum, t;
+ unsigned char *e, *e2;
+#if HAVE_FAST_64BIT
+ typedef uint64_t wsum_t;
+#else
+ typedef uint32_t wsum_t;
+#endif
+ wsum_t wsum;
+
+ for(sum=0; h; h--, p+=s-w)
+ {
+ for(shift=0, e=p+w; (int)p&(sizeof(wsum_t)-1) && p<e;)
+ sum^=*p++<<(shift=(shift-8)&31);
+
+ for(wsum=0, e2=e-sizeof(wsum_t)+1; p<e2; p+=sizeof(wsum_t))
+ wsum^=*(wsum_t *)p;
+
+#if HAVE_FAST_64BIT
+ t=be2me_32((uint32_t)(wsum>>32^wsum));
+#else
+ t=be2me_32(wsum);
+#endif
+
+ for(sum^=(t<<shift|t>>(32-shift)); p<e;)
+ sum^=*p++<<(shift=(shift-8)&31);
+ }
+
+ return sum;
+ }
+
+static int deghost_plane(unsigned char *d, unsigned char *s,
+ int w, int h, int ds, int ss, int threshold)
+ {
+ int t;
+ unsigned char *e;
+
+ for(; h; h--, s+=ss-w, d+=ds-w)
+ for(e=d+w; d<e; d++, s++)
+ if(abs(*d-*s)>=threshold)
+ *d=(t=(*d<<1)-*s)<0?0:t>255?255:t;
+
+ return 0;
+ }
+
+static int copyop(unsigned char *d, unsigned char *s, int bpl, int h, int dstride, int sstride, int dummy) {
+ memcpy_pic(d, s, bpl, h, dstride, sstride);
+ return 0;
+}
+
+static int imgop(int(*planeop)(unsigned char *, unsigned char *,
+ int, int, int, int, int),
+ mp_image_t *dst, mp_image_t *src, int arg)
+ {
+ if(dst->flags&MP_IMGFLAG_PLANAR)
+ return planeop(dst->planes[0], src?src->planes[0]:0,
+ dst->w, dst->h,
+ dst->stride[0], src?src->stride[0]:0, arg)+
+ planeop(dst->planes[1], src?src->planes[1]:0,
+ dst->chroma_width, dst->chroma_height,
+ dst->stride[1], src?src->stride[1]:0, arg)+
+ planeop(dst->planes[2], src?src->planes[2]:0,
+ dst->chroma_width, dst->chroma_height,
+ dst->stride[2], src?src->stride[2]:0, arg);
+
+ return planeop(dst->planes[0], src?src->planes[0]:0,
+ dst->w*(dst->bpp/8), dst->h,
+ dst->stride[0], src?src->stride[0]:0, arg);
+ }
+
+/*
+ * Find the phase in which the telecine pattern fits best to the
+ * given 5 frame slice of frame difference measurements.
+ *
+ * If phase1 and phase2 are not negative, only the two specified
+ * phases are tested.
+ */
+
+static int match(struct vf_priv_s *p, int *diffs,
+ int phase1, int phase2, double *strength)
+ {
+ static const int pattern1[]={ -4, 1, 1, 1, 1 },
+ pattern2[]={ -2, -3, 4, 4, -3 }, *pattern;
+ int f, m, n, t[5];
+
+ pattern=p->deghost>0?pattern2:pattern1;
+
+ for(f=0; f<5; f++)
+ {
+ if(phase1<0 || phase2<0 || f==phase1 || f==phase2)
+ {
+ for(n=t[f]=0; n<5; n++)
+ t[f]+=diffs[n]*pattern[(n-f+5)%5];
+ }
+ else
+ t[f]=INT_MIN;
+ }
+
+ /* find the best match */
+ for(m=0, n=1; n<5; n++)
+ if(t[n]>t[m]) m=n;
+
+ if(strength)
+ {
+ /* the second best match */
+ for(f=m?0:1, n=f+1; n<5; n++)
+ if(n!=m && t[n]>t[f]) f=n;
+
+ *strength=(t[m]>0?(double)(t[m]-t[f])/t[m]:0.0);
+ }
+
+ return m;
+ }
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+ {
+ mp_image_t *dmpi, *tmpi=0;
+ int n, m, f, newphase;
+ struct vf_priv_s *p=vf->priv;
+ unsigned int checksum;
+ double d;
+
+ dmpi=vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
+ mpi->width, mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ newphase=p->phase;
+
+ switch(p->pass)
+ {
+ case 1:
+ fprintf(p->file, "%08x %d\n",
+ (unsigned int)imgop((void *)checksum_plane, mpi, 0, 0),
+ p->frameno?imgop(diff_plane, dmpi, mpi, 0):0);
+ break;
+
+ case 2:
+ if(p->frameno/5>p->bcount)
+ {
+ mp_msg(MSGT_VFILTER, MSGL_ERR,
+ "\n%s: Log file ends prematurely! "
+ "Switching to one pass mode.\n", vf->info->name);
+ p->pass=0;
+ break;
+ }
+
+ checksum=(unsigned int)imgop((void *)checksum_plane, mpi, 0, 0);
+
+ if(checksum!=p->csdata[p->frameno])
+ {
+ for(f=0; f<100; f++)
+ if(p->frameno+f<p->fcount && p->csdata[p->frameno+f]==checksum)
+ break;
+ else if(p->frameno-f>=0 && p->csdata[p->frameno-f]==checksum)
+ {
+ f=-f;
+ break;
+ }
+
+ if(f<100)
+ {
+ mp_msg(MSGT_VFILTER, MSGL_INFO,
+ "\n%s: Mismatch with pass-1: %+d frame(s).\n",
+ vf->info->name, f);
+
+ p->frameno+=f;
+ p->misscount=0;
+ }
+ else if(p->misscount++>=30)
+ {
+ mp_msg(MSGT_VFILTER, MSGL_ERR,
+ "\n%s: Sync with pass-1 lost! "
+ "Switching to one pass mode.\n", vf->info->name);
+ p->pass=0;
+ break;
+ }
+ }
+
+ n=(p->frameno)/5;
+ if(n>=p->bcount) n=p->bcount-1;
+
+ newphase=p->bdata[n];
+ break;
+
+ default:
+ if(p->frameno)
+ {
+ int *sump=p->sum+p->frameno%5,
+ *histp=p->history+p->frameno%p->window;
+
+ *sump-=*histp;
+ *sump+=(*histp=imgop(diff_plane, dmpi, mpi, 0));
+ }
+
+ m=match(p, p->sum, -1, -1, &d);
+
+ if(d>=p->threshold)
+ newphase=m;
+ }
+
+ n=p->ocount++%5;
+
+ if(newphase!=p->phase && ((p->phase+4)%5<n)==((newphase+4)%5<n))
+ {
+ p->phase=newphase;
+ mp_msg(MSGT_VFILTER, MSGL_STATUS,
+ "\n%s: Telecine phase %d.\n", vf->info->name, p->phase);
+ }
+
+ switch((p->frameno++-p->phase+10)%5)
+ {
+ case 0:
+ imgop(copyop, dmpi, mpi, 0);
+ return 0;
+
+ case 4:
+ if(p->deghost>0)
+ {
+ tmpi=vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_READABLE,
+ mpi->width, mpi->height);
+ vf_clone_mpi_attributes(tmpi, mpi);
+
+ imgop(copyop, tmpi, mpi, 0);
+ imgop(deghost_plane, tmpi, dmpi, p->deghost);
+ imgop(copyop, dmpi, mpi, 0);
+ return vf_next_put_image(vf, tmpi, MP_NOPTS_VALUE);
+ }
+ }
+
+ imgop(copyop, dmpi, mpi, 0);
+ return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ }
+
+static int analyze(struct vf_priv_s *p)
+ {
+ int *buf=0, *bp, bufsize=0, n, b, f, i, j, m, s;
+ unsigned int *cbuf=0, *cp;
+ char *pbuf;
+ char lbuf[256];
+ int sum[5];
+ double d;
+
+ /* read the file */
+
+ n=15;
+ while(fgets(lbuf, 256, p->file))
+ {
+ if(n>=bufsize-19)
+ {
+ bufsize=bufsize?bufsize*2:30000;
+ if((bp=realloc(buf, bufsize*sizeof *buf))) buf=bp;
+ if((cp=realloc(cbuf, bufsize*sizeof *cbuf))) cbuf=cp;
+
+ if(!bp || !cp)
+ {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Not enough memory.\n",
+ vf_info_divtc.name);
+ free(buf);
+ free(cbuf);
+ return 0;
+ }
+ }
+ sscanf(lbuf, "%x %d", cbuf+n, buf+n);
+ n++;
+ }
+
+ if(!n)
+ {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Empty 2-pass log file.\n",
+ vf_info_divtc.name);
+ free(buf);
+ free(cbuf);
+ return 0;
+ }
+
+ /* generate some dummy data past the beginning and end of the array */
+
+ buf+=15, cbuf+=15;
+ n-=15;
+
+ memcpy(buf-15, buf, 15*sizeof *buf);
+ memset(cbuf-15, 0, 15*sizeof *cbuf);
+
+ while(n%5)
+ buf[n]=buf[n-5], cbuf[n]=0, n++;
+
+ memcpy(buf+n, buf+n-15, 15*sizeof *buf);
+ memset(cbuf+n, 0, 15*sizeof *cbuf);
+
+ p->csdata=cbuf;
+ p->fcount=n;
+
+ /* array with one slot for each slice of 5 frames */
+
+ p->bdata=pbuf=malloc(p->bcount=b=(n/5));
+ memset(pbuf, 255, b);
+
+ /* resolve the automatic mode */
+
+ if(p->deghost<0)
+ {
+ int deghost=-p->deghost;
+ double s0=0.0, s1=0.0;
+
+ for(f=0; f<n; f+=5)
+ {
+ p->deghost=0; match(p, buf+f, -1, -1, &d); s0+=d;
+ p->deghost=1; match(p, buf+f, -1, -1, &d); s1+=d;
+ }
+
+ p->deghost=s1>s0?deghost:0;
+
+ mp_msg(MSGT_VFILTER, MSGL_INFO,
+ "%s: Deghosting %-3s (relative pattern strength %+.2fdB).\n",
+ vf_info_divtc.name,
+ p->deghost?"ON":"OFF",
+ 10.0*log10(s1/s0));
+ }
+
+ /* analyze the data */
+
+ for(f=0; f<5; f++)
+ for(sum[f]=0, n=-15; n<20; n+=5)
+ sum[f]+=buf[n+f];
+
+ for(f=0; f<b; f++)
+ {
+ m=match(p, sum, -1, -1, &d);
+
+ if(d>=p->threshold)
+ pbuf[f]=m;
+
+ if(f<b-1)
+ for(n=0; n<5; n++)
+ sum[n]=sum[n]-buf[5*(f-3)+n]+buf[5*(f+4)+n];
+ }
+
+ /* fill in the gaps */
+
+ /* the beginning */
+ for(f=0; f<b && pbuf[f]==-1; f++);
+
+ if(f==b)
+ {
+ free(buf-15);
+ mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: No telecine pattern found!\n",
+ vf_info_divtc.name);
+ return 0;
+ }
+
+ for(n=0; n<f; pbuf[n++]=pbuf[f]);
+
+ /* the end */
+ for(f=b-1; pbuf[f]==-1; f--);
+ for(n=f+1; n<b; pbuf[n++]=pbuf[f]);
+
+ /* the rest */
+ for(f=0;;)
+ {
+ while(f<b && pbuf[f]!=-1) f++;
+ if(f==b) break;
+ for(n=f; pbuf[n]==-1; n++);
+
+ if(pbuf[f-1]==pbuf[n])
+ {
+ /* just a gap */
+ while(f<n) pbuf[f++]=pbuf[n];
+ }
+ else
+ {
+ /* phase change, reanalyze the original data in the gap with zero
+ threshold for only the two phases that appear at the ends */
+
+ for(i=0; i<5; i++)
+ for(sum[i]=0, j=5*f-15; j<5*f; j+=5)
+ sum[i]+=buf[i+j];
+
+ for(i=f; i<n; i++)
+ {
+ pbuf[i]=match(p, sum, pbuf[f-1], pbuf[n], 0);
+
+ for(j=0; j<5; j++)
+ sum[j]=sum[j]-buf[5*(i-3)+j]+buf[5*(i+4)+j];
+ }
+
+ /* estimate the transition point by dividing the gap
+ in the same proportion as the number of matches of each kind */
+
+ for(i=f, m=f; i<n; i++)
+ if(pbuf[i]==pbuf[f-1]) m++;
+
+ /* find the transition of the right direction nearest to the
+ estimated point */
+
+ if(m>f && m<n)
+ {
+ for(j=m; j>f; j--)
+ if(pbuf[j-1]==pbuf[f-1] && pbuf[j]==pbuf[n]) break;
+ for(s=m; s<n; s++)
+ if(pbuf[s-1]==pbuf[f-1] && pbuf[s]==pbuf[n]) break;
+
+ m=(s-m<m-j)?s:j;
+ }
+
+ /* and rewrite the data to allow only this one transition */
+
+ for(i=f; i<m; i++)
+ pbuf[i]=pbuf[f-1];
+
+ for(; i<n; i++)
+ pbuf[i]=pbuf[n];
+
+ f=n;
+ }
+ }
+
+ free(buf-15);
+
+ return 1;
+ }
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+ {
+ switch(fmt)
+ {
+ case IMGFMT_444P: case IMGFMT_IYUV: case IMGFMT_RGB24:
+ case IMGFMT_422P: case IMGFMT_UYVY: case IMGFMT_BGR24:
+ case IMGFMT_411P: case IMGFMT_YUY2: case IMGFMT_IF09:
+ case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_YVU9:
+ case IMGFMT_IUYV: case IMGFMT_Y800: case IMGFMT_Y8:
+ return vf_next_query_format(vf,fmt);
+ }
+
+ return 0;
+ }
+
+static void uninit(struct vf_instance *vf)
+ {
+ if(vf->priv)
+ {
+ if(vf->priv->file) fclose(vf->priv->file);
+ if(vf->priv->csdata) free(vf->priv->csdata-15);
+ free(vf->priv->bdata);
+ free(vf->priv->history);
+ free(vf->priv);
+ }
+ }
+
+static int vf_open(vf_instance_t *vf, char *args)
+ {
+ struct vf_priv_s *p;
+ char *filename="framediff.log", *ap, *q, *a;
+
+ if(args && !(args=strdup(args)))
+ {
+ nomem:
+ mp_msg(MSGT_VFILTER, MSGL_FATAL,
+ "%s: Not enough memory.\n", vf->info->name);
+ fail:
+ uninit(vf);
+ free(args);
+ return 0;
+ }
+
+ vf->put_image=put_image;
+ vf->uninit=uninit;
+ vf->query_format=query_format;
+ vf->default_reqs=VFCAP_ACCEPT_STRIDE;
+ if(!(vf->priv=p=calloc(1, sizeof(struct vf_priv_s))))
+ goto nomem;
+
+ p->phase=5;
+ p->threshold=0.5;
+ p->window=30;
+
+ if((ap=args))
+ while(*ap)
+ {
+ q=ap;
+ if((ap=strchr(q, ':'))) *ap++=0; else ap=q+strlen(q);
+ if((a=strchr(q, '='))) *a++=0; else a=q+strlen(q);
+
+ switch(*q)
+ {
+ case 0: break;
+ case 'f': filename=a; break;
+ case 't': p->threshold=atof(a); break;
+ case 'w': p->window=5*(atoi(a)+4)/5; break;
+ case 'd': p->deghost=atoi(a); break;
+ case 'p':
+ if(q[1]=='h') p->phase=atoi(a);
+ else p->pass=atoi(a);
+ break;
+
+ case 'h':
+ mp_msg(MSGT_VFILTER, MSGL_INFO,
+ "\n%s options:\n\n"
+ "pass=1|2 - Use 2-pass mode.\n"
+ "file=filename - Set the 2-pass log file name "
+ "(default %s).\n"
+ "threshold=value - Set the pattern recognition "
+ "sensitivity (default %g).\n"
+ "deghost=value - Select deghosting threshold "
+ "(default %d).\n"
+ "window=numframes - Set the statistics window "
+ "for 1-pass mode (default %d).\n"
+ "phase=0|1|2|3|4 - Set the initial phase "
+ "for 1-pass mode (default %d).\n\n"
+ "The option names can be abbreviated to the shortest "
+ "unique prefix.\n\n",
+ vf->info->name, filename, p->threshold, p->deghost,
+ p->window, p->phase%5);
+ break;
+
+ default:
+ mp_msg(MSGT_VFILTER, MSGL_FATAL,
+ "%s: Unknown argument %s.\n", vf->info->name, q);
+ goto fail;
+ }
+ }
+
+ switch(p->pass)
+ {
+ case 1:
+ if(!(p->file=fopen(filename, "w")))
+ {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL,
+ "%s: Can't create file %s.\n", vf->info->name, filename);
+ goto fail;
+ }
+
+ break;
+
+ case 2:
+ if(!(p->file=fopen(filename, "r")))
+ {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL,
+ "%s: Can't open file %s.\n", vf->info->name, filename);
+ goto fail;
+ }
+
+ if(!analyze(p))
+ goto fail;
+
+ fclose(p->file);
+ p->file=0;
+ break;
+ }
+
+ if(p->window<5) p->window=5;
+ if(!(p->history=calloc(sizeof *p->history, p->window)))
+ goto nomem;
+
+ diff = diff_C;
+#if HAVE_MMX && HAVE_EBX_AVAILABLE
+ if(gCpuCaps.hasMMX) diff = diff_MMX;
+#endif
+
+ free(args);
+ return 1;
+ }
+
+const vf_info_t vf_info_divtc =
+ {
+ "inverse telecine for deinterlaced video",
+ "divtc",
+ "Ville Saari",
+ "",
+ vf_open,
+ NULL
+ };
diff --git a/libavfilter/libmpcodecs/vf_down3dright.c b/libavfilter/libmpcodecs/vf_down3dright.c
new file mode 100644
index 0000000000..4dba19a2f0
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_down3dright.c
@@ -0,0 +1,166 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+struct vf_priv_s {
+ int skipline;
+ int scalew;
+ int scaleh;
+};
+
+static void toright(unsigned char *dst[3], unsigned char *src[3],
+ int dststride[3], int srcstride[3],
+ int w, int h, struct vf_priv_s* p)
+{
+ int k;
+
+ for (k = 0; k < 3; k++) {
+ unsigned char* fromL = src[k];
+ unsigned char* fromR = src[k];
+ unsigned char* to = dst[k];
+ int src = srcstride[k];
+ int dst = dststride[k];
+ int ss;
+ unsigned int dd;
+ int i;
+
+ if (k > 0) {
+ i = h / 4 - p->skipline / 2;
+ ss = src * (h / 4 + p->skipline / 2);
+ dd = w / 4;
+ } else {
+ i = h / 2 - p->skipline;
+ ss = src * (h / 2 + p->skipline);
+ dd = w / 2;
+ }
+ fromR += ss;
+ for ( ; i > 0; i--) {
+ int j;
+ unsigned char* t = to;
+ unsigned char* sL = fromL;
+ unsigned char* sR = fromR;
+
+ if (p->scalew == 1) {
+ for (j = dd; j > 0; j--) {
+ *t++ = (sL[0] + sL[1]) / 2;
+ sL+=2;
+ }
+ for (j = dd ; j > 0; j--) {
+ *t++ = (sR[0] + sR[1]) / 2;
+ sR+=2;
+ }
+ } else {
+ for (j = dd * 2 ; j > 0; j--)
+ *t++ = *sL++;
+ for (j = dd * 2 ; j > 0; j--)
+ *t++ = *sR++;
+ }
+ if (p->scaleh == 1) {
+ fast_memcpy(to + dst, to, dst);
+ to += dst;
+ }
+ to += dst;
+ fromL += src;
+ fromR += src;
+ }
+ //printf("K %d %d %d %d %d \n", k, w, h, src, dst);
+ }
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next, IMGFMT_YV12,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE |
+ (vf->priv->scaleh == 1) ? MP_IMGFLAG_READABLE : 0,
+ mpi->w * vf->priv->scalew,
+ mpi->h / vf->priv->scaleh - vf->priv->skipline);
+
+ toright(dmpi->planes, mpi->planes, dmpi->stride,
+ mpi->stride, mpi->w, mpi->h, vf->priv);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ /* FIXME - also support UYVY output? */
+ return vf_next_config(vf, width * vf->priv->scalew,
+ height / vf->priv->scaleh - vf->priv->skipline, d_width, d_height, flags, IMGFMT_YV12);
+}
+
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - really any YUV 4:2:0 input format should work */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf, IMGFMT_YV12);
+ }
+ return 0;
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->config=config;
+ vf->query_format=query_format;
+ vf->put_image=put_image;
+ vf->uninit=uninit;
+
+ vf->priv = calloc(1, sizeof (struct vf_priv_s));
+ vf->priv->skipline = 0;
+ vf->priv->scalew = 1;
+ vf->priv->scaleh = 2;
+ if (args) sscanf(args, "%d:%d:%d", &vf->priv->skipline, &vf->priv->scalew, &vf->priv->scaleh);
+
+ return 1;
+}
+
+const vf_info_t vf_info_down3dright = {
+ "convert stereo movie from top-bottom to left-right field",
+ "down3dright",
+ "Zdenek Kabelac",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_dsize.c b/libavfilter/libmpcodecs/vf_dsize.c
new file mode 100644
index 0000000000..7772b3732d
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_dsize.c
@@ -0,0 +1,123 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ int w, h;
+ int method; // aspect method, 0 -> downscale, 1-> upscale. +2 -> original aspect.
+ int round;
+ float aspect;
+};
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ if (vf->priv->aspect < 0.001) { // did the user input aspect or w,h params
+ if (vf->priv->w == 0) vf->priv->w = d_width;
+ if (vf->priv->h == 0) vf->priv->h = d_height;
+ if (vf->priv->w == -1) vf->priv->w = width;
+ if (vf->priv->h == -1) vf->priv->h = height;
+ if (vf->priv->w == -2) vf->priv->w = vf->priv->h * (double)d_width / d_height;
+ if (vf->priv->w == -3) vf->priv->w = vf->priv->h * (double)width / height;
+ if (vf->priv->h == -2) vf->priv->h = vf->priv->w * (double)d_height / d_width;
+ if (vf->priv->h == -3) vf->priv->h = vf->priv->w * (double)height / width;
+ if (vf->priv->method > -1) {
+ double aspect = (vf->priv->method & 2) ? ((double)height / width) : ((double)d_height / d_width);
+ if ((vf->priv->h > vf->priv->w * aspect) ^ (vf->priv->method & 1)) {
+ vf->priv->h = vf->priv->w * aspect;
+ } else {
+ vf->priv->w = vf->priv->h / aspect;
+ }
+ }
+ if (vf->priv->round > 1) { // round up
+ vf->priv->w += (vf->priv->round - 1 - (vf->priv->w - 1) % vf->priv->round);
+ vf->priv->h += (vf->priv->round - 1 - (vf->priv->h - 1) % vf->priv->round);
+ }
+ d_width = vf->priv->w;
+ d_height = vf->priv->h;
+ } else {
+ if (vf->priv->aspect * height > width) {
+ d_width = height * vf->priv->aspect + .5;
+ d_height = height;
+ } else {
+ d_height = width / vf->priv->aspect + .5;
+ d_width = width;
+ }
+ }
+ return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
+}
+
+static void uninit(vf_instance_t *vf) {
+ free(vf->priv);
+ vf->priv = NULL;
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->config = config;
+ vf->draw_slice = vf_next_draw_slice;
+ vf->uninit = uninit;
+ //vf->default_caps = 0;
+ vf->priv = calloc(sizeof(struct vf_priv_s), 1);
+ vf->priv->aspect = 0.;
+ vf->priv->w = -1;
+ vf->priv->h = -1;
+ vf->priv->method = -1;
+ vf->priv->round = 1;
+ if (args) {
+ if (strchr(args, '/')) {
+ int w, h;
+ sscanf(args, "%d/%d", &w, &h);
+ vf->priv->aspect = (float)w/h;
+ } else if (strchr(args, '.')) {
+ sscanf(args, "%f", &vf->priv->aspect);
+ } else {
+ sscanf(args, "%d:%d:%d:%d", &vf->priv->w, &vf->priv->h, &vf->priv->method, &vf->priv->round);
+ }
+ }
+ if ((vf->priv->aspect < 0.) || (vf->priv->w < -3) || (vf->priv->h < -3) ||
+ ((vf->priv->w < -1) && (vf->priv->h < -1)) ||
+ (vf->priv->method < -1) || (vf->priv->method > 3) ||
+ (vf->priv->round < 0)) {
+ mp_msg(MSGT_VFILTER, MSGL_ERR, "[dsize] Illegal value(s): aspect: %f w: %d h: %d aspect_method: %d round: %d\n", vf->priv->aspect, vf->priv->w, vf->priv->h, vf->priv->method, vf->priv->round);
+ free(vf->priv); vf->priv = NULL;
+ return -1;
+ }
+ return 1;
+}
+
+const vf_info_t vf_info_dsize = {
+ "reset displaysize/aspect",
+ "dsize",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_eq.c b/libavfilter/libmpcodecs/vf_eq.c
new file mode 100644
index 0000000000..d68e860a02
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_eq.c
@@ -0,0 +1,258 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/video_out.h"
+
+#include "m_option.h"
+#include "m_struct.h"
+
+static struct vf_priv_s {
+ unsigned char *buf;
+ int brightness;
+ int contrast;
+} const vf_priv_dflt = {
+ NULL,
+ 0,
+ 0
+};
+
+#if HAVE_MMX
+static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, int sstride,
+ int w, int h, int brightness, int contrast)
+{
+ int i;
+ int pel;
+ int dstep = dstride-w;
+ int sstep = sstride-w;
+ short brvec[4];
+ short contvec[4];
+
+ contrast = ((contrast+100)*256*16)/100;
+ brightness = ((brightness+100)*511)/200-128 - contrast/32;
+
+ brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness;
+ contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast;
+
+ while (h--) {
+ __asm__ volatile (
+ "movq (%5), %%mm3 \n\t"
+ "movq (%6), %%mm4 \n\t"
+ "pxor %%mm0, %%mm0 \n\t"
+ "movl %4, %%eax\n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%0), %%mm1 \n\t"
+ "movq (%0), %%mm2 \n\t"
+ "punpcklbw %%mm0, %%mm1 \n\t"
+ "punpckhbw %%mm0, %%mm2 \n\t"
+ "psllw $4, %%mm1 \n\t"
+ "psllw $4, %%mm2 \n\t"
+ "pmulhw %%mm4, %%mm1 \n\t"
+ "pmulhw %%mm4, %%mm2 \n\t"
+ "paddw %%mm3, %%mm1 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "packuswb %%mm2, %%mm1 \n\t"
+ "add $8, %0 \n\t"
+ "movq %%mm1, (%1) \n\t"
+ "add $8, %1 \n\t"
+ "decl %%eax \n\t"
+ "jnz 1b \n\t"
+ : "=r" (src), "=r" (dest)
+ : "0" (src), "1" (dest), "r" (w>>3), "r" (brvec), "r" (contvec)
+ : "%eax"
+ );
+
+ for (i = w&7; i; i--)
+ {
+ pel = ((*src++* contrast)>>12) + brightness;
+ if(pel&768) pel = (-pel)>>31;
+ *dest++ = pel;
+ }
+
+ src += sstep;
+ dest += dstep;
+ }
+ __asm__ volatile ( "emms \n\t" ::: "memory" );
+}
+#endif
+
+static void process_C(unsigned char *dest, int dstride, unsigned char *src, int sstride,
+ int w, int h, int brightness, int contrast)
+{
+ int i;
+ int pel;
+ int dstep = dstride-w;
+ int sstep = sstride-w;
+
+ contrast = ((contrast+100)*256*256)/100;
+ brightness = ((brightness+100)*511)/200-128 - contrast/512;
+
+ while (h--) {
+ for (i = w; i; i--)
+ {
+ pel = ((*src++* contrast)>>16) + brightness;
+ if(pel&768) pel = (-pel)>>31;
+ *dest++ = pel;
+ }
+ src += sstep;
+ dest += dstep;
+ }
+}
+
+static void (*process)(unsigned char *dest, int dstride, unsigned char *src, int sstride,
+ int w, int h, int brightness, int contrast);
+
+/* FIXME: add packed yuv version of process */
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+
+ dmpi=vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, 0,
+ mpi->w, mpi->h);
+
+ dmpi->stride[0] = mpi->stride[0];
+ dmpi->planes[1] = mpi->planes[1];
+ dmpi->planes[2] = mpi->planes[2];
+ dmpi->stride[1] = mpi->stride[1];
+ dmpi->stride[2] = mpi->stride[2];
+
+ if (!vf->priv->buf) vf->priv->buf = malloc(mpi->stride[0]*mpi->h);
+
+ if ((vf->priv->brightness == 0) && (vf->priv->contrast == 0))
+ dmpi->planes[0] = mpi->planes[0];
+ else {
+ dmpi->planes[0] = vf->priv->buf;
+ process(dmpi->planes[0], dmpi->stride[0],
+ mpi->planes[0], mpi->stride[0],
+ mpi->w, mpi->h, vf->priv->brightness,
+ vf->priv->contrast);
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static int control(struct vf_instance *vf, int request, void* data)
+{
+ vf_equalizer_t *eq;
+
+ switch (request) {
+ case VFCTRL_SET_EQUALIZER:
+ eq = data;
+ if (!strcmp(eq->item,"brightness")) {
+ vf->priv->brightness = eq->value;
+ return CONTROL_TRUE;
+ }
+ else if (!strcmp(eq->item,"contrast")) {
+ vf->priv->contrast = eq->value;
+ return CONTROL_TRUE;
+ }
+ break;
+ case VFCTRL_GET_EQUALIZER:
+ eq = data;
+ if (!strcmp(eq->item,"brightness")) {
+ eq->value = vf->priv->brightness;
+ return CONTROL_TRUE;
+ }
+ else if (!strcmp(eq->item,"contrast")) {
+ eq->value = vf->priv->contrast;
+ return CONTROL_TRUE;
+ }
+ break;
+ }
+ return vf_next_control(vf, request, data);
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ switch (fmt) {
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_NV12:
+ case IMGFMT_NV21:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv->buf);
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->control=control;
+ vf->query_format=query_format;
+ vf->put_image=put_image;
+ vf->uninit=uninit;
+
+ process = process_C;
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX) process = process_MMX;
+#endif
+
+ return 1;
+}
+
+#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
+static const m_option_t vf_opts_fields[] = {
+ {"brightness", ST_OFF(brightness), CONF_TYPE_INT, M_OPT_RANGE,-100 ,100, NULL},
+ {"contrast", ST_OFF(contrast), CONF_TYPE_INT, M_OPT_RANGE,-100 ,100, NULL},
+ { NULL, NULL, 0, 0, 0, 0, NULL }
+};
+
+static const m_struct_t vf_opts = {
+ "eq",
+ sizeof(struct vf_priv_s),
+ &vf_priv_dflt,
+ vf_opts_fields
+};
+
+const vf_info_t vf_info_eq = {
+ "soft video equalizer",
+ "eq",
+ "Richard Felker",
+ "",
+ vf_open,
+ &vf_opts
+};
diff --git a/libavfilter/libmpcodecs/vf_eq2.c b/libavfilter/libmpcodecs/vf_eq2.c
new file mode 100644
index 0000000000..fe4a89fb13
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_eq2.c
@@ -0,0 +1,519 @@
+/*
+ * Software equalizer (brightness, contrast, gamma, saturation)
+ *
+ * Hampa Hug <hampa@hampa.ch> (original LUT gamma/contrast/brightness filter)
+ * Daniel Moreno <comac@comac.darktech.org> (saturation, R/G/B gamma support)
+ * Richard Felker (original MMX contrast/brightness code (vf_eq.c))
+ * Michael Niedermayer <michalni@gmx.at> (LUT16)
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#define LUT16
+
+/* Per channel parameters */
+typedef struct eq2_param_t {
+ unsigned char lut[256];
+#ifdef LUT16
+ uint16_t lut16[256*256];
+#endif
+ int lut_clean;
+
+ void (*adjust) (struct eq2_param_t *par, unsigned char *dst, unsigned char *src,
+ unsigned w, unsigned h, unsigned dstride, unsigned sstride);
+
+ double c;
+ double b;
+ double g;
+ double w;
+} eq2_param_t;
+
+typedef struct vf_priv_s {
+ eq2_param_t param[3];
+
+ double contrast;
+ double brightness;
+ double saturation;
+
+ double gamma;
+ double gamma_weight;
+ double rgamma;
+ double ggamma;
+ double bgamma;
+
+ unsigned buf_w[3];
+ unsigned buf_h[3];
+ unsigned char *buf[3];
+} vf_eq2_t;
+
+
+static
+void create_lut (eq2_param_t *par)
+{
+ unsigned i;
+ double g, v;
+ double lw, gw;
+
+ g = par->g;
+ gw = par->w;
+ lw = 1.0 - gw;
+
+ if ((g < 0.001) || (g > 1000.0)) {
+ g = 1.0;
+ }
+
+ g = 1.0 / g;
+
+ for (i = 0; i < 256; i++) {
+ v = (double) i / 255.0;
+ v = par->c * (v - 0.5) + 0.5 + par->b;
+
+ if (v <= 0.0) {
+ par->lut[i] = 0;
+ }
+ else {
+ v = v*lw + pow(v, g)*gw;
+
+ if (v >= 1.0) {
+ par->lut[i] = 255;
+ }
+ else {
+ par->lut[i] = (unsigned char) (256.0 * v);
+ }
+ }
+ }
+
+#ifdef LUT16
+ for(i=0; i<256*256; i++){
+ par->lut16[i]= par->lut[i&0xFF] + (par->lut[i>>8]<<8);
+ }
+#endif
+
+ par->lut_clean = 1;
+}
+
+#if HAVE_MMX
+static
+void affine_1d_MMX (eq2_param_t *par, unsigned char *dst, unsigned char *src,
+ unsigned w, unsigned h, unsigned dstride, unsigned sstride)
+{
+ unsigned i;
+ int contrast, brightness;
+ unsigned dstep, sstep;
+ int pel;
+ short brvec[4];
+ short contvec[4];
+
+// printf("\nmmx: src=%p dst=%p w=%d h=%d ds=%d ss=%d\n",src,dst,w,h,dstride,sstride);
+
+ contrast = (int) (par->c * 256 * 16);
+ brightness = ((int) (100.0 * par->b + 100.0) * 511) / 200 - 128 - contrast / 32;
+
+ brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness;
+ contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast;
+
+ sstep = sstride - w;
+ dstep = dstride - w;
+
+ while (h-- > 0) {
+ __asm__ volatile (
+ "movq (%5), %%mm3 \n\t"
+ "movq (%6), %%mm4 \n\t"
+ "pxor %%mm0, %%mm0 \n\t"
+ "movl %4, %%eax\n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%0), %%mm1 \n\t"
+ "movq (%0), %%mm2 \n\t"
+ "punpcklbw %%mm0, %%mm1 \n\t"
+ "punpckhbw %%mm0, %%mm2 \n\t"
+ "psllw $4, %%mm1 \n\t"
+ "psllw $4, %%mm2 \n\t"
+ "pmulhw %%mm4, %%mm1 \n\t"
+ "pmulhw %%mm4, %%mm2 \n\t"
+ "paddw %%mm3, %%mm1 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "packuswb %%mm2, %%mm1 \n\t"
+ "add $8, %0 \n\t"
+ "movq %%mm1, (%1) \n\t"
+ "add $8, %1 \n\t"
+ "decl %%eax \n\t"
+ "jnz 1b \n\t"
+ : "=r" (src), "=r" (dst)
+ : "0" (src), "1" (dst), "r" (w >> 3), "r" (brvec), "r" (contvec)
+ : "%eax"
+ );
+
+ for (i = w & 7; i > 0; i--) {
+ pel = ((*src++ * contrast) >> 12) + brightness;
+ if (pel & 768) {
+ pel = (-pel) >> 31;
+ }
+ *dst++ = pel;
+ }
+
+ src += sstep;
+ dst += dstep;
+ }
+
+ __asm__ volatile ( "emms \n\t" ::: "memory" );
+}
+#endif
+
+static
+void apply_lut (eq2_param_t *par, unsigned char *dst, unsigned char *src,
+ unsigned w, unsigned h, unsigned dstride, unsigned sstride)
+{
+ unsigned i, j, w2;
+ unsigned char *lut;
+ uint16_t *lut16;
+
+ if (!par->lut_clean) {
+ create_lut (par);
+ }
+
+ lut = par->lut;
+#ifdef LUT16
+ lut16 = par->lut16;
+ w2= (w>>3)<<2;
+ for (j = 0; j < h; j++) {
+ uint16_t *src16= (uint16_t*)src;
+ uint16_t *dst16= (uint16_t*)dst;
+ for (i = 0; i < w2; i+=4) {
+ dst16[i+0] = lut16[src16[i+0]];
+ dst16[i+1] = lut16[src16[i+1]];
+ dst16[i+2] = lut16[src16[i+2]];
+ dst16[i+3] = lut16[src16[i+3]];
+ }
+ i <<= 1;
+#else
+ w2= (w>>3)<<3;
+ for (j = 0; j < h; j++) {
+ for (i = 0; i < w2; i+=8) {
+ dst[i+0] = lut[src[i+0]];
+ dst[i+1] = lut[src[i+1]];
+ dst[i+2] = lut[src[i+2]];
+ dst[i+3] = lut[src[i+3]];
+ dst[i+4] = lut[src[i+4]];
+ dst[i+5] = lut[src[i+5]];
+ dst[i+6] = lut[src[i+6]];
+ dst[i+7] = lut[src[i+7]];
+ }
+#endif
+ for (; i < w; i++) {
+ dst[i] = lut[src[i]];
+ }
+
+ src += sstride;
+ dst += dstride;
+ }
+}
+
+static
+int put_image (vf_instance_t *vf, mp_image_t *src, double pts)
+{
+ unsigned i;
+ vf_eq2_t *eq2;
+ mp_image_t *dst;
+ unsigned long img_n,img_c;
+
+ eq2 = vf->priv;
+
+ if ((eq2->buf_w[0] != src->w) || (eq2->buf_h[0] != src->h)) {
+ eq2->buf_w[0] = src->w;
+ eq2->buf_h[0] = src->h;
+ eq2->buf_w[1] = eq2->buf_w[2] = src->w >> src->chroma_x_shift;
+ eq2->buf_h[1] = eq2->buf_h[2] = src->h >> src->chroma_y_shift;
+ img_n = eq2->buf_w[0]*eq2->buf_h[0];
+ if(src->num_planes>1){
+ img_c = eq2->buf_w[1]*eq2->buf_h[1];
+ eq2->buf[0] = realloc (eq2->buf[0], img_n + 2*img_c);
+ eq2->buf[1] = eq2->buf[0] + img_n;
+ eq2->buf[2] = eq2->buf[1] + img_c;
+ } else
+ eq2->buf[0] = realloc (eq2->buf[0], img_n);
+ }
+
+ dst = vf_get_image (vf->next, src->imgfmt, MP_IMGTYPE_EXPORT, 0, src->w, src->h);
+
+ for (i = 0; i < ((src->num_planes>1)?3:1); i++) {
+ if (eq2->param[i].adjust != NULL) {
+ dst->planes[i] = eq2->buf[i];
+ dst->stride[i] = eq2->buf_w[i];
+
+ eq2->param[i].adjust (&eq2->param[i], dst->planes[i], src->planes[i],
+ eq2->buf_w[i], eq2->buf_h[i], dst->stride[i], src->stride[i]);
+ }
+ else {
+ dst->planes[i] = src->planes[i];
+ dst->stride[i] = src->stride[i];
+ }
+ }
+
+ return vf_next_put_image (vf, dst, pts);
+}
+
+static
+void check_values (eq2_param_t *par)
+{
+ /* yuck! floating point comparisons... */
+
+ if ((par->c == 1.0) && (par->b == 0.0) && (par->g == 1.0)) {
+ par->adjust = NULL;
+ }
+#if HAVE_MMX
+ else if (par->g == 1.0 && gCpuCaps.hasMMX) {
+ par->adjust = &affine_1d_MMX;
+ }
+#endif
+ else {
+ par->adjust = &apply_lut;
+ }
+}
+
+static
+void print_values (vf_eq2_t *eq2)
+{
+ mp_msg (MSGT_VFILTER, MSGL_V, "vf_eq2: c=%.2f b=%.2f g=%.4f s=%.2f \n",
+ eq2->contrast, eq2->brightness, eq2->gamma, eq2->saturation
+ );
+}
+
+static
+void set_contrast (vf_eq2_t *eq2, double c)
+{
+ eq2->contrast = c;
+ eq2->param[0].c = c;
+ eq2->param[0].lut_clean = 0;
+ check_values (&eq2->param[0]);
+ print_values (eq2);
+}
+
+static
+void set_brightness (vf_eq2_t *eq2, double b)
+{
+ eq2->brightness = b;
+ eq2->param[0].b = b;
+ eq2->param[0].lut_clean = 0;
+ check_values (&eq2->param[0]);
+ print_values (eq2);
+}
+
+static
+void set_gamma (vf_eq2_t *eq2, double g)
+{
+ eq2->gamma = g;
+
+ eq2->param[0].g = eq2->gamma * eq2->ggamma;
+ eq2->param[1].g = sqrt (eq2->bgamma / eq2->ggamma);
+ eq2->param[2].g = sqrt (eq2->rgamma / eq2->ggamma);
+ eq2->param[0].w = eq2->param[1].w = eq2->param[2].w = eq2->gamma_weight;
+
+ eq2->param[0].lut_clean = 0;
+ eq2->param[1].lut_clean = 0;
+ eq2->param[2].lut_clean = 0;
+
+ check_values (&eq2->param[0]);
+ check_values (&eq2->param[1]);
+ check_values (&eq2->param[2]);
+
+ print_values (eq2);
+}
+
+static
+void set_saturation (vf_eq2_t *eq2, double s)
+{
+ eq2->saturation = s;
+
+ eq2->param[1].c = s;
+ eq2->param[2].c = s;
+
+ eq2->param[1].lut_clean = 0;
+ eq2->param[2].lut_clean = 0;
+
+ check_values (&eq2->param[1]);
+ check_values (&eq2->param[2]);
+
+ print_values (eq2);
+}
+
+static
+int control (vf_instance_t *vf, int request, void *data)
+{
+ vf_equalizer_t *eq;
+
+ switch (request) {
+ case VFCTRL_SET_EQUALIZER:
+ eq = (vf_equalizer_t *) data;
+
+ if (strcmp (eq->item, "gamma") == 0) {
+ set_gamma (vf->priv, exp (log (8.0) * eq->value / 100.0));
+ return CONTROL_TRUE;
+ }
+ else if (strcmp (eq->item, "contrast") == 0) {
+ set_contrast (vf->priv, (1.0 / 100.0) * (eq->value + 100));
+ return CONTROL_TRUE;
+ }
+ else if (strcmp (eq->item, "brightness") == 0) {
+ set_brightness (vf->priv, (1.0 / 100.0) * eq->value);
+ return CONTROL_TRUE;
+ }
+ else if (strcmp (eq->item, "saturation") == 0) {
+ set_saturation (vf->priv, (double) (eq->value + 100) / 100.0);
+ return CONTROL_TRUE;
+ }
+ break;
+
+ case VFCTRL_GET_EQUALIZER:
+ eq = (vf_equalizer_t *) data;
+ if (strcmp (eq->item, "gamma") == 0) {
+ eq->value = (int) (100.0 * log (vf->priv->gamma) / log (8.0));
+ return CONTROL_TRUE;
+ }
+ else if (strcmp (eq->item, "contrast") == 0) {
+ eq->value = (int) (100.0 * vf->priv->contrast) - 100;
+ return CONTROL_TRUE;
+ }
+ else if (strcmp (eq->item, "brightness") == 0) {
+ eq->value = (int) (100.0 * vf->priv->brightness);
+ return CONTROL_TRUE;
+ }
+ else if (strcmp (eq->item, "saturation") == 0) {
+ eq->value = (int) (100.0 * vf->priv->saturation) - 100;
+ return CONTROL_TRUE;
+ }
+ break;
+ }
+
+ return vf_next_control (vf, request, data);
+}
+
+static
+int query_format (vf_instance_t *vf, unsigned fmt)
+{
+ switch (fmt) {
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format (vf, fmt);
+ }
+
+ return 0;
+}
+
+static
+void uninit (vf_instance_t *vf)
+{
+ if (vf->priv != NULL) {
+ free (vf->priv->buf[0]);
+ free (vf->priv);
+ }
+}
+
+static
+int vf_open(vf_instance_t *vf, char *args)
+{
+ unsigned i;
+ vf_eq2_t *eq2;
+ double par[8];
+
+ vf->control = control;
+ vf->query_format = query_format;
+ vf->put_image = put_image;
+ vf->uninit = uninit;
+
+ vf->priv = malloc (sizeof (vf_eq2_t));
+ eq2 = vf->priv;
+
+ for (i = 0; i < 3; i++) {
+ eq2->buf[i] = NULL;
+ eq2->buf_w[i] = 0;
+ eq2->buf_h[i] = 0;
+
+ eq2->param[i].adjust = NULL;
+ eq2->param[i].c = 1.0;
+ eq2->param[i].b = 0.0;
+ eq2->param[i].g = 1.0;
+ eq2->param[i].lut_clean = 0;
+ }
+
+ eq2->contrast = 1.0;
+ eq2->brightness = 0.0;
+ eq2->saturation = 1.0;
+
+ eq2->gamma = 1.0;
+ eq2->gamma_weight = 1.0;
+ eq2->rgamma = 1.0;
+ eq2->ggamma = 1.0;
+ eq2->bgamma = 1.0;
+
+ if (args != NULL) {
+ par[0] = 1.0;
+ par[1] = 1.0;
+ par[2] = 0.0;
+ par[3] = 1.0;
+ par[4] = 1.0;
+ par[5] = 1.0;
+ par[6] = 1.0;
+ par[7] = 1.0;
+ sscanf (args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf",
+ par, par + 1, par + 2, par + 3, par + 4, par + 5, par + 6, par + 7
+ );
+
+ eq2->rgamma = par[4];
+ eq2->ggamma = par[5];
+ eq2->bgamma = par[6];
+ eq2->gamma_weight = par[7];
+
+ set_gamma (eq2, par[0]);
+ set_contrast (eq2, par[1]);
+ set_brightness (eq2, par[2]);
+ set_saturation (eq2, par[3]);
+ }
+
+ return 1;
+}
+
+const vf_info_t vf_info_eq2 = {
+ "Software equalizer",
+ "eq2",
+ "Hampa Hug, Daniel Moreno, Richard Felker",
+ "",
+ &vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_field.c b/libavfilter/libmpcodecs/vf_field.c
new file mode 100644
index 0000000000..fcf24be0bc
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_field.c
@@ -0,0 +1,89 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ int field;
+};
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ return vf_next_config(vf,width,height/2,d_width,d_height,flags,outfmt);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->width, mpi->height/2);
+
+ // set up mpi as a double-stride image of dmpi:
+ vf->dmpi->planes[0]=mpi->planes[0]+mpi->stride[0]*vf->priv->field;
+ vf->dmpi->stride[0]=2*mpi->stride[0];
+ if(vf->dmpi->flags&MP_IMGFLAG_PLANAR){
+ vf->dmpi->planes[1]=mpi->planes[1]+
+ mpi->stride[1]*vf->priv->field;
+ vf->dmpi->stride[1]=2*mpi->stride[1];
+ vf->dmpi->planes[2]=mpi->planes[2]+
+ mpi->stride[2]*vf->priv->field;
+ vf->dmpi->stride[2]=2*mpi->stride[2];
+ } else
+ vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!!
+
+ return vf_next_put_image(vf,vf->dmpi, pts);
+}
+
+//===========================================================================//
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->uninit=uninit;
+ vf->default_reqs=VFCAP_ACCEPT_STRIDE;
+ vf->priv=calloc(1, sizeof(struct vf_priv_s));
+ if (args) sscanf(args, "%d", &vf->priv->field);
+ vf->priv->field &= 1;
+ return 1;
+}
+
+const vf_info_t vf_info_field = {
+ "extract single field",
+ "field",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_fil.c b/libavfilter/libmpcodecs/vf_fil.c
new file mode 100644
index 0000000000..7df7eb0af7
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_fil.c
@@ -0,0 +1,116 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ int interleave;
+ int height;
+ int width;
+ int stridefactor;
+};
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ int pixel_stride= (width+15)&~15; //FIXME this is ust a guess ... especially for non planar its somewhat bad one
+
+#if 0
+ if(mpi->flags&MP_IMGFLAG_PLANAR)
+ pixel_stride= mpi->stride[0];
+ else
+ pixel_stride= 8*mpi->stride[0] / mpi->bpp;
+
+#endif
+
+ if(vf->priv->interleave){
+ vf->priv->height= 2*height;
+ vf->priv->width= width - (pixel_stride/2);
+ vf->priv->stridefactor=1;
+ }else{
+ vf->priv->height= height/2;
+ vf->priv->width= width + pixel_stride;
+ vf->priv->stridefactor=4;
+ }
+//printf("hX %d %d %d\n", vf->priv->width,vf->priv->height,vf->priv->stridefactor);
+
+ return vf_next_config(vf, vf->priv->width, vf->priv->height,
+ (d_width*vf->priv->stridefactor)>>1, 2*d_height/vf->priv->stridefactor, flags, outfmt);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ if(mpi->flags&MP_IMGFLAG_DIRECT){
+ // we've used DR, so we're ready...
+ return vf_next_put_image(vf,(mp_image_t*)mpi->priv, pts);
+ }
+
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
+ vf->priv->width, vf->priv->height);
+
+ // set up mpi as a double-stride image of dmpi:
+ vf->dmpi->planes[0]=mpi->planes[0];
+ vf->dmpi->stride[0]=(mpi->stride[0]*vf->priv->stridefactor)>>1;
+ if(vf->dmpi->flags&MP_IMGFLAG_PLANAR){
+ vf->dmpi->planes[1]=mpi->planes[1];
+ vf->dmpi->stride[1]=(mpi->stride[1]*vf->priv->stridefactor)>>1;
+ vf->dmpi->planes[2]=mpi->planes[2];
+ vf->dmpi->stride[2]=(mpi->stride[2]*vf->priv->stridefactor)>>1;
+ } else
+ vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!!
+
+ return vf_next_put_image(vf,vf->dmpi, pts);
+}
+
+//===========================================================================//
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->uninit=uninit;
+ vf->default_reqs=VFCAP_ACCEPT_STRIDE;
+ vf->priv=calloc(1, sizeof(struct vf_priv_s));
+ vf->priv->interleave= args && (*args == 'i');
+ return 1;
+}
+
+const vf_info_t vf_info_fil = {
+ "fast (de)interleaver",
+ "fil",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_filmdint.c b/libavfilter/libmpcodecs/vf_filmdint.c
new file mode 100644
index 0000000000..70db246e1d
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_filmdint.c
@@ -0,0 +1,1461 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vd.h"
+#include "vf.h"
+#include "cmmx.h"
+
+#include "libvo/fastmemcpy.h"
+
+#define NUM_STORED 4
+
+enum pu_field_type_t {
+ PU_1ST_OF_3,
+ PU_2ND_OF_3,
+ PU_3RD_OF_3,
+ PU_1ST_OF_2,
+ PU_2ND_OF_2,
+ PU_INTERLACED
+};
+
+struct metrics {
+ /* This struct maps to a packed word 64-bit MMX register */
+ unsigned short int even;
+ unsigned short int odd;
+ unsigned short int noise;
+ unsigned short int temp;
+} __attribute__ ((aligned (8)));
+
+struct frame_stats {
+ struct metrics tiny, low, high, bigger, twox, max;
+ struct { unsigned int even, odd, noise, temp; } sad;
+ unsigned short interlaced_high;
+ unsigned short interlaced_low;
+ unsigned short num_blocks;
+};
+
+struct vf_priv_s {
+ unsigned long inframes;
+ unsigned long outframes;
+ enum pu_field_type_t prev_type;
+ unsigned swapped, chroma_swapped;
+ unsigned luma_only;
+ unsigned verbose;
+ unsigned fast;
+ unsigned long w, h, cw, ch, stride, chroma_stride, nplanes;
+ unsigned long sad_thres;
+ unsigned long dint_thres;
+ unsigned char *memory_allocated;
+ unsigned char *planes[2*NUM_STORED][4];
+ unsigned char **old_planes;
+ unsigned long static_idx;
+ unsigned long temp_idx;
+ unsigned long crop_x, crop_y, crop_cx, crop_cy;
+ unsigned long export_count, merge_count;
+ unsigned long num_breaks;
+ unsigned long num_copies;
+ long in_inc, out_dec, iosync;
+ long num_fields;
+ long prev_fields;
+ long notout;
+ long mmx2;
+ unsigned small_bytes[2];
+ unsigned mmx_temp[2];
+ struct frame_stats stats[2];
+ struct metrics thres;
+ char chflag;
+ double diff_time, merge_time, decode_time, vo_time, filter_time;
+};
+
+#define PPZ { 2000, 2000, 0, 2000 }
+#define PPR { 2000, 2000, 0, 2000 }
+static const struct frame_stats ppzs = {PPZ,PPZ,PPZ,PPZ,PPZ,PPZ,PPZ,0,0,9999};
+static const struct frame_stats pprs = {PPR,PPR,PPR,PPR,PPR,PPR,PPR,0,0,9999};
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef MAX
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#define PDIFFUB(X,Y,T) "movq " #X "," #T "\n\t" \
+ "psubusb " #Y "," #T "\n\t" \
+ "psubusb " #X "," #Y "\n\t" \
+ "paddusb " #Y "," #T "\n\t"
+
+#define PDIFFUBT(X,Y,T) "movq " #X "," #T "\n\t" \
+ "psubusb " #Y "," #T "\n\t" \
+ "psubusb " #X "," #Y "\n\t" \
+ "paddusb " #T "," #Y "\n\t"
+
+#define PSUMBW(X,T,Z) "movq " #X "," #T "\n\t" \
+ "punpcklbw " #Z "," #X "\n\t" \
+ "punpckhbw " #Z "," #T "\n\t" \
+ "paddw " #T "," #X "\n\t" \
+ "movq " #X "," #T "\n\t" \
+ "psllq $32, " #T "\n\t" \
+ "paddw " #T "," #X "\n\t" \
+ "movq " #X "," #T "\n\t" \
+ "psllq $16, " #T "\n\t" \
+ "paddw " #T "," #X "\n\t" \
+ "psrlq $48, " #X "\n\t"
+
+#define PSADBW(X,Y,T,Z) PDIFFUBT(X,Y,T) PSUMBW(Y,T,Z)
+
+#define PMAXUB(X,Y) "psubusb " #X "," #Y "\n\tpaddusb " #X "," #Y "\n\t"
+#define PMAXUW(X,Y) "psubusw " #X "," #Y "\n\tpaddusw " #X "," #Y "\n\t"
+#define PMINUBT(X,Y,T) "movq " #Y "," #T "\n\t" \
+ "psubusb " #X "," #T "\n\t" \
+ "psubusb " #T "," #Y "\n\t"
+#define PAVGB(X,Y) "pavgusb " #X "," #Y "\n\t"
+
+static inline void
+get_metrics_c(unsigned char *a, unsigned char *b, int as, int bs, int lines,
+ struct metrics *m)
+{
+ a -= as;
+ b -= bs;
+ do {
+ cmmx_t old_po = *(cmmx_t*)(a );
+ cmmx_t po = *(cmmx_t*)(b );
+ cmmx_t e = *(cmmx_t*)(b + bs);
+ cmmx_t old_o = *(cmmx_t*)(a + 2*as);
+ cmmx_t o = *(cmmx_t*)(b + 2*bs);
+ cmmx_t ne = *(cmmx_t*)(b + 3*bs);
+ cmmx_t old_no = *(cmmx_t*)(a + 4*as);
+ cmmx_t no = *(cmmx_t*)(b + 4*bs);
+
+ cmmx_t qup_old_odd = p31avgb(old_o, old_po);
+ cmmx_t qup_odd = p31avgb( o, po);
+ cmmx_t qdown_old_odd = p31avgb(old_o, old_no);
+ cmmx_t qdown_odd = p31avgb( o, no);
+
+ cmmx_t qup_even = p31avgb(ne, e);
+ cmmx_t qdown_even = p31avgb(e, ne);
+
+ cmmx_t temp_up_diff = pdiffub(qdown_even, qup_old_odd);
+ cmmx_t noise_up_diff = pdiffub(qdown_even, qup_odd);
+ cmmx_t temp_down_diff = pdiffub(qup_even, qdown_old_odd);
+ cmmx_t noise_down_diff = pdiffub(qup_even, qdown_odd);
+
+ cmmx_t odd_diff = pdiffub(o, old_o);
+ m->odd += psumbw(odd_diff);
+ m->even += psadbw(e, *(cmmx_t*)(a+as));
+
+ temp_up_diff = pminub(temp_up_diff, temp_down_diff);
+ temp_up_diff = pminub(temp_up_diff, odd_diff);
+ m->temp += psumbw(temp_up_diff);
+ noise_up_diff = pminub(noise_up_diff, odd_diff);
+ noise_up_diff = pminub(noise_up_diff, noise_down_diff);
+
+ m->noise += psumbw(noise_up_diff);
+ a += 2*as;
+ b += 2*bs;
+ } while (--lines);
+}
+
+static inline void
+get_metrics_fast_c(unsigned char *a, unsigned char *b, int as, int bs,
+ int lines, struct metrics *m)
+{
+ a -= as;
+ b -= bs;
+ do {
+ cmmx_t old_po = (*(cmmx_t*)(a ) >> 1) & ~SIGN_BITS;
+ cmmx_t po = (*(cmmx_t*)(b ) >> 1) & ~SIGN_BITS;
+ cmmx_t old_e = (*(cmmx_t*)(a + as) >> 1) & ~SIGN_BITS;
+ cmmx_t e = (*(cmmx_t*)(b + bs) >> 1) & ~SIGN_BITS;
+ cmmx_t old_o = (*(cmmx_t*)(a + 2*as) >> 1) & ~SIGN_BITS;
+ cmmx_t o = (*(cmmx_t*)(b + 2*bs) >> 1) & ~SIGN_BITS;
+ cmmx_t ne = (*(cmmx_t*)(b + 3*bs) >> 1) & ~SIGN_BITS;
+ cmmx_t old_no = (*(cmmx_t*)(a + 4*as) >> 1) & ~SIGN_BITS;
+ cmmx_t no = (*(cmmx_t*)(b + 4*bs) >> 1) & ~SIGN_BITS;
+
+ cmmx_t qup_old_odd = p31avgb_s(old_o, old_po);
+ cmmx_t qup_odd = p31avgb_s( o, po);
+ cmmx_t qdown_old_odd = p31avgb_s(old_o, old_no);
+ cmmx_t qdown_odd = p31avgb_s( o, no);
+
+ cmmx_t qup_even = p31avgb_s(ne, e);
+ cmmx_t qdown_even = p31avgb_s(e, ne);
+
+ cmmx_t temp_up_diff = pdiffub_s(qdown_even, qup_old_odd);
+ cmmx_t noise_up_diff = pdiffub_s(qdown_even, qup_odd);
+ cmmx_t temp_down_diff = pdiffub_s(qup_even, qdown_old_odd);
+ cmmx_t noise_down_diff = pdiffub_s(qup_even, qdown_odd);
+
+ cmmx_t odd_diff = pdiffub_s(o, old_o);
+ m->odd += psumbw_s(odd_diff) << 1;
+ m->even += psadbw_s(e, old_e) << 1;
+
+ temp_up_diff = pminub_s(temp_up_diff, temp_down_diff);
+ temp_up_diff = pminub_s(temp_up_diff, odd_diff);
+ m->temp += psumbw_s(temp_up_diff) << 1;
+ noise_up_diff = pminub_s(noise_up_diff, odd_diff);
+ noise_up_diff = pminub_s(noise_up_diff, noise_down_diff);
+
+ m->noise += psumbw_s(noise_up_diff) << 1;
+ a += 2*as;
+ b += 2*bs;
+ } while (--lines);
+}
+
+static inline void
+get_metrics_faster_c(unsigned char *a, unsigned char *b, int as, int bs,
+ int lines, struct metrics *m)
+{
+ a -= as;
+ b -= bs;
+ do {
+ cmmx_t old_po = (*(cmmx_t*)(a )>>1) & ~SIGN_BITS;
+ cmmx_t po = (*(cmmx_t*)(b )>>1) & ~SIGN_BITS;
+ cmmx_t old_e = (*(cmmx_t*)(a + as)>>1) & ~SIGN_BITS;
+ cmmx_t e = (*(cmmx_t*)(b + bs)>>1) & ~SIGN_BITS;
+ cmmx_t old_o = (*(cmmx_t*)(a + 2*as)>>1) & ~SIGN_BITS;
+ cmmx_t o = (*(cmmx_t*)(b + 2*bs)>>1) & ~SIGN_BITS;
+ cmmx_t ne = (*(cmmx_t*)(b + 3*bs)>>1) & ~SIGN_BITS;
+
+ cmmx_t down_even = p31avgb_s(e, ne);
+ cmmx_t up_odd = p31avgb_s(o, po);
+ cmmx_t up_old_odd = p31avgb_s(old_o, old_po);
+
+ cmmx_t odd_diff = pdiffub_s(o, old_o);
+ cmmx_t temp_diff = pdiffub_s(down_even, up_old_odd);
+ cmmx_t noise_diff = pdiffub_s(down_even, up_odd);
+
+ m->even += psadbw_s(e, old_e) << 1;
+ m->odd += psumbw_s(odd_diff) << 1;
+
+ temp_diff = pminub_s(temp_diff, odd_diff);
+ noise_diff = pminub_s(noise_diff, odd_diff);
+
+ m->noise += psumbw_s(noise_diff) << 1;
+ m->temp += psumbw_s(temp_diff) << 1;
+ a += 2*as;
+ b += 2*bs;
+ } while (--lines);
+
+}
+
+static inline void
+get_block_stats(struct metrics *m, struct vf_priv_s *p, struct frame_stats *s)
+{
+ unsigned two_e = m->even + MAX(m->even , p->thres.even );
+ unsigned two_o = m->odd + MAX(m->odd , p->thres.odd );
+ unsigned two_n = m->noise + MAX(m->noise, p->thres.noise);
+ unsigned two_t = m->temp + MAX(m->temp , p->thres.temp );
+
+ unsigned e_big = m->even >= (m->odd + two_o + 1)/2;
+ unsigned o_big = m->odd >= (m->even + two_e + 1)/2;
+ unsigned n_big = m->noise >= (m->temp + two_t + 1)/2;
+ unsigned t_big = m->temp >= (m->noise + two_n + 1)/2;
+
+ unsigned e2x = m->even >= two_o;
+ unsigned o2x = m->odd >= two_e;
+ unsigned n2x = m->noise >= two_t;
+ unsigned t2x = m->temp >= two_n;
+
+ unsigned ntiny_e = m->even > p->thres.even ;
+ unsigned ntiny_o = m->odd > p->thres.odd ;
+ unsigned ntiny_n = m->noise > p->thres.noise;
+ unsigned ntiny_t = m->temp > p->thres.temp ;
+
+ unsigned nlow_e = m->even > 2*p->thres.even ;
+ unsigned nlow_o = m->odd > 2*p->thres.odd ;
+ unsigned nlow_n = m->noise > 2*p->thres.noise;
+ unsigned nlow_t = m->temp > 2*p->thres.temp ;
+
+ unsigned high_e = m->even > 4*p->thres.even ;
+ unsigned high_o = m->odd > 4*p->thres.odd ;
+ unsigned high_n = m->noise > 4*p->thres.noise;
+ unsigned high_t = m->temp > 4*p->thres.temp ;
+
+ unsigned low_il = !n_big && !t_big && ntiny_n && ntiny_t;
+ unsigned high_il = !n_big && !t_big && nlow_n && nlow_t;
+
+ if (low_il | high_il) {
+ s->interlaced_low += low_il;
+ s->interlaced_high += high_il;
+ } else {
+ s->tiny.even += ntiny_e;
+ s->tiny.odd += ntiny_o;
+ s->tiny.noise += ntiny_n;
+ s->tiny.temp += ntiny_t;
+
+ s->low .even += nlow_e ;
+ s->low .odd += nlow_o ;
+ s->low .noise += nlow_n ;
+ s->low .temp += nlow_t ;
+
+ s->high.even += high_e ;
+ s->high.odd += high_o ;
+ s->high.noise += high_n ;
+ s->high.temp += high_t ;
+
+ if (m->even >= p->sad_thres) s->sad.even += m->even ;
+ if (m->odd >= p->sad_thres) s->sad.odd += m->odd ;
+ if (m->noise >= p->sad_thres) s->sad.noise += m->noise;
+ if (m->temp >= p->sad_thres) s->sad.temp += m->temp ;
+ }
+ s->num_blocks++;
+ s->max.even = MAX(s->max.even , m->even );
+ s->max.odd = MAX(s->max.odd , m->odd );
+ s->max.noise = MAX(s->max.noise, m->noise);
+ s->max.temp = MAX(s->max.temp , m->temp );
+
+ s->bigger.even += e_big ;
+ s->bigger.odd += o_big ;
+ s->bigger.noise += n_big ;
+ s->bigger.temp += t_big ;
+
+ s->twox.even += e2x ;
+ s->twox.odd += o2x ;
+ s->twox.noise += n2x ;
+ s->twox.temp += t2x ;
+
+}
+
+static inline struct metrics
+block_metrics_c(unsigned char *a, unsigned char *b, int as, int bs,
+ int lines, struct vf_priv_s *p, struct frame_stats *s)
+{
+ struct metrics tm;
+ tm.even = tm.odd = tm.noise = tm.temp = 0;
+ get_metrics_c(a, b, as, bs, lines, &tm);
+ if (sizeof(cmmx_t) < 8)
+ get_metrics_c(a+4, b+4, as, bs, lines, &tm);
+ get_block_stats(&tm, p, s);
+ return tm;
+}
+
+static inline struct metrics
+block_metrics_fast_c(unsigned char *a, unsigned char *b, int as, int bs,
+ int lines, struct vf_priv_s *p, struct frame_stats *s)
+{
+ struct metrics tm;
+ tm.even = tm.odd = tm.noise = tm.temp = 0;
+ get_metrics_fast_c(a, b, as, bs, lines, &tm);
+ if (sizeof(cmmx_t) < 8)
+ get_metrics_fast_c(a+4, b+4, as, bs, lines, &tm);
+ get_block_stats(&tm, p, s);
+ return tm;
+}
+
+static inline struct metrics
+block_metrics_faster_c(unsigned char *a, unsigned char *b, int as, int bs,
+ int lines, struct vf_priv_s *p, struct frame_stats *s)
+{
+ struct metrics tm;
+ tm.even = tm.odd = tm.noise = tm.temp = 0;
+ get_metrics_faster_c(a, b, as, bs, lines, &tm);
+ if (sizeof(cmmx_t) < 8)
+ get_metrics_faster_c(a+4, b+4, as, bs, lines, &tm);
+ get_block_stats(&tm, p, s);
+ return tm;
+}
+
+#define MEQ(X,Y) ((X).even == (Y).even && (X).odd == (Y).odd && (X).temp == (Y).temp && (X).noise == (Y).noise)
+
+#define BLOCK_METRICS_TEMPLATE() \
+ __asm__ volatile("pxor %mm7, %mm7\n\t" /* The result is colleted in mm7 */ \
+ "pxor %mm6, %mm6\n\t" /* Temp to stay at 0 */ \
+ ); \
+ a -= as; \
+ b -= bs; \
+ do { \
+ __asm__ volatile( \
+ "movq (%0,%2), %%mm0\n\t" \
+ "movq (%1,%3), %%mm1\n\t" /* mm1 = even */ \
+ PSADBW(%%mm1, %%mm0, %%mm4, %%mm6) \
+ "paddusw %%mm0, %%mm7\n\t" /* even diff */ \
+ "movq (%0,%2,2), %%mm0\n\t" /* mm0 = old odd */ \
+ "movq (%1,%3,2), %%mm2\n\t" /* mm2 = odd */ \
+ "movq (%0), %%mm3\n\t" \
+ "psubusb %4, %%mm3\n\t" \
+ PAVGB(%%mm0, %%mm3) \
+ PAVGB(%%mm0, %%mm3) /* mm3 = qup old odd */ \
+ "movq %%mm0, %%mm5\n\t" \
+ PSADBW(%%mm2, %%mm0, %%mm4, %%mm6) \
+ "psllq $16, %%mm0\n\t" \
+ "paddusw %%mm0, %%mm7\n\t" \
+ "movq (%1), %%mm4\n\t" \
+ "lea (%0,%2,2), %0\n\t" \
+ "lea (%1,%3,2), %1\n\t" \
+ "psubusb %4, %%mm4\n\t" \
+ PAVGB(%%mm2, %%mm4) \
+ PAVGB(%%mm2, %%mm4) /* mm4 = qup odd */ \
+ PDIFFUBT(%%mm5, %%mm2, %%mm0) /* mm2 =abs(oldodd-odd) */ \
+ "movq (%1,%3), %%mm5\n\t" \
+ "psubusb %4, %%mm5\n\t" \
+ PAVGB(%%mm1, %%mm5) \
+ PAVGB(%%mm5, %%mm1) /* mm1 = qdown even */ \
+ PAVGB((%1,%3), %%mm5) /* mm5 = qup next even */ \
+ PDIFFUBT(%%mm1, %%mm3, %%mm0) /* mm3 = abs(qupoldo-qde) */ \
+ PDIFFUBT(%%mm1, %%mm4, %%mm0) /* mm4 = abs(qupodd-qde) */ \
+ PMINUBT(%%mm2, %%mm3, %%mm0) /* limit temp to odd diff */ \
+ PMINUBT(%%mm2, %%mm4, %%mm0) /* limit noise to odd diff */ \
+ "movq (%1,%3,2), %%mm2\n\t" \
+ "psubusb %4, %%mm2\n\t" \
+ PAVGB((%1), %%mm2) \
+ PAVGB((%1), %%mm2) /* mm2 = qdown odd */ \
+ "movq (%0,%2,2), %%mm1\n\t" \
+ "psubusb %4, %%mm1\n\t" \
+ PAVGB((%0), %%mm1) \
+ PAVGB((%0), %%mm1) /* mm1 = qdown old odd */ \
+ PDIFFUBT(%%mm5, %%mm2, %%mm0) /* mm2 = abs(qdo-qune) */ \
+ PDIFFUBT(%%mm5, %%mm1, %%mm0) /* mm1 = abs(qdoo-qune) */ \
+ PMINUBT(%%mm4, %%mm2, %%mm0) /* current */ \
+ PMINUBT(%%mm3, %%mm1, %%mm0) /* old */ \
+ PSUMBW(%%mm2, %%mm0, %%mm6) \
+ PSUMBW(%%mm1, %%mm0, %%mm6) \
+ "psllq $32, %%mm2\n\t" \
+ "psllq $48, %%mm1\n\t" \
+ "paddusw %%mm2, %%mm7\n\t" \
+ "paddusw %%mm1, %%mm7\n\t" \
+ : "=r" (a), "=r" (b) \
+ : "r"((x86_reg)as), "r"((x86_reg)bs), "m" (ones), "0"(a), "1"(b), "X"(*a), "X"(*b) \
+ ); \
+ } while (--lines);
+
+static inline struct metrics
+block_metrics_3dnow(unsigned char *a, unsigned char *b, int as, int bs,
+ int lines, struct vf_priv_s *p, struct frame_stats *s)
+{
+ struct metrics tm;
+#if !HAVE_AMD3DNOW
+ mp_msg(MSGT_VFILTER, MSGL_FATAL, "block_metrics_3dnow: internal error\n");
+#else
+ static const unsigned long long ones = 0x0101010101010101ull;
+
+ BLOCK_METRICS_TEMPLATE();
+ __asm__ volatile("movq %%mm7, %0\n\temms" : "=m" (tm));
+ get_block_stats(&tm, p, s);
+#endif
+ return tm;
+}
+
+#undef PSUMBW
+#undef PSADBW
+#undef PMAXUB
+#undef PMINUBT
+#undef PAVGB
+
+#define PSUMBW(X,T,Z) "psadbw " #Z "," #X "\n\t"
+#define PSADBW(X,Y,T,Z) "psadbw " #X "," #Y "\n\t"
+#define PMAXUB(X,Y) "pmaxub " #X "," #Y "\n\t"
+#define PMINUBT(X,Y,T) "pminub " #X "," #Y "\n\t"
+#define PAVGB(X,Y) "pavgb " #X "," #Y "\n\t"
+
+static inline struct metrics
+block_metrics_mmx2(unsigned char *a, unsigned char *b, int as, int bs,
+ int lines, struct vf_priv_s *p, struct frame_stats *s)
+{
+ struct metrics tm;
+#if !HAVE_MMX
+ mp_msg(MSGT_VFILTER, MSGL_FATAL, "block_metrics_mmx2: internal error\n");
+#else
+ static const unsigned long long ones = 0x0101010101010101ull;
+ x86_reg interlaced;
+ x86_reg prefetch_line = (((long)a>>3) & 7) + 10;
+#ifdef DEBUG
+ struct frame_stats ts = *s;
+#endif
+ __asm__ volatile("prefetcht0 (%0,%2)\n\t"
+ "prefetcht0 (%1,%3)\n\t" :
+ : "r" (a), "r" (b),
+ "r" (prefetch_line * as), "r" (prefetch_line * bs));
+
+ BLOCK_METRICS_TEMPLATE();
+
+ s->num_blocks++;
+ __asm__ volatile(
+ "movq %3, %%mm0\n\t"
+ "movq %%mm7, %%mm1\n\t"
+ "psubusw %%mm0, %%mm1\n\t"
+ "movq %%mm1, %%mm2\n\t"
+ "paddusw %%mm0, %%mm2\n\t"
+ "paddusw %%mm7, %%mm2\n\t"
+ "pshufw $0xb1, %%mm2, %%mm3\n\t"
+ "pavgw %%mm7, %%mm2\n\t"
+ "pshufw $0xb1, %%mm2, %%mm2\n\t"
+ "psubusw %%mm7, %%mm2\n\t"
+ "pcmpeqw %%mm6, %%mm2\n\t" /* 1 if >= 1.5x */
+ "psubusw %%mm7, %%mm3\n\t"
+ "pcmpeqw %%mm6, %%mm3\n\t" /* 1 if >= 2x */
+ "movq %1, %%mm4\n\t"
+ "movq %2, %%mm5\n\t"
+ "psubw %%mm2, %%mm4\n\t"
+ "psubw %%mm3, %%mm5\n\t"
+ "movq %%mm4, %1\n\t"
+ "movq %%mm5, %2\n\t"
+ "pxor %%mm4, %%mm4\n\t"
+ "pcmpeqw %%mm1, %%mm4\n\t" /* 1 if <= t */
+ "psubusw %%mm0, %%mm1\n\t"
+ "pxor %%mm5, %%mm5\n\t"
+ "pcmpeqw %%mm1, %%mm5\n\t" /* 1 if <= 2t */
+ "psubusw %%mm0, %%mm1\n\t"
+ "psubusw %%mm0, %%mm1\n\t"
+ "pcmpeqw %%mm6, %%mm1\n\t" /* 1 if <= 4t */
+ "pshufw $0xb1, %%mm2, %%mm0\n\t"
+ "por %%mm2, %%mm0\n\t" /* 1 if not close */
+ "punpckhdq %%mm0, %%mm0\n\t"
+ "movq %%mm4, %%mm2\n\t" /* tttt */
+ "punpckhdq %%mm5, %%mm2\n\t" /* ttll */
+ "por %%mm2, %%mm0\n\t"
+ "pcmpeqd %%mm6, %%mm0\n\t" /* close && big */
+ "psrlq $16, %%mm0\n\t"
+ "psrlw $15, %%mm0\n\t"
+ "movd %%mm0, %0\n\t"
+ : "=r" (interlaced), "=m" (s->bigger), "=m" (s->twox)
+ : "m" (p->thres)
+ );
+
+ if (interlaced) {
+ s->interlaced_high += interlaced >> 16;
+ s->interlaced_low += interlaced;
+ } else {
+ __asm__ volatile(
+ "pcmpeqw %%mm0, %%mm0\n\t" /* -1 */
+ "psubw %%mm0, %%mm4\n\t"
+ "psubw %%mm0, %%mm5\n\t"
+ "psubw %%mm0, %%mm1\n\t"
+ "paddw %0, %%mm4\n\t"
+ "paddw %1, %%mm5\n\t"
+ "paddw %2, %%mm1\n\t"
+ "movq %%mm4, %0\n\t"
+ "movq %%mm5, %1\n\t"
+ "movq %%mm1, %2\n\t"
+ : "=m" (s->tiny), "=m" (s->low), "=m" (s->high)
+ );
+
+ __asm__ volatile(
+ "pshufw $0, %2, %%mm0\n\t"
+ "psubusw %%mm7, %%mm0\n\t"
+ "pcmpeqw %%mm6, %%mm0\n\t" /* 0 if below sad_thres */
+ "pand %%mm7, %%mm0\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "punpcklwd %%mm6, %%mm0\n\t" /* sad even, odd */
+ "punpckhwd %%mm6, %%mm1\n\t" /* sad noise, temp */
+ "paddd %0, %%mm0\n\t"
+ "paddd %1, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, %1\n\t"
+ : "=m" (s->sad.even), "=m" (s->sad.noise)
+ : "m" (p->sad_thres)
+ );
+ }
+
+ __asm__ volatile(
+ "movq %%mm7, (%1)\n\t"
+ PMAXUW((%0), %%mm7)
+ "movq %%mm7, (%0)\n\t"
+ "emms"
+ : : "r" (&s->max), "r" (&tm), "X" (s->max)
+ : "memory"
+ );
+#ifdef DEBUG
+ if (1) {
+ struct metrics cm;
+ a -= 7*as;
+ b -= 7*bs;
+ cm = block_metrics_c(a, b, as, bs, 4, p, &ts);
+ if (!MEQ(tm, cm))
+ mp_msg(MSGT_VFILTER, MSGL_WARN, "Bad metrics\n");
+ if (s) {
+# define CHECK(X) if (!MEQ(s->X, ts.X)) \
+ mp_msg(MSGT_VFILTER, MSGL_WARN, "Bad " #X "\n");
+ CHECK(tiny);
+ CHECK(low);
+ CHECK(high);
+ CHECK(sad);
+ CHECK(max);
+ }
+ }
+#endif
+#endif
+ return tm;
+}
+
+static inline int
+dint_copy_line_mmx2(unsigned char *dst, unsigned char *a, long bos,
+ long cos, int ds, int ss, int w, int t)
+{
+#if !HAVE_MMX
+ mp_msg(MSGT_VFILTER, MSGL_FATAL, "dint_copy_line_mmx2: internal error\n");
+ return 0;
+#else
+ unsigned long len = (w+7) >> 3;
+ int ret;
+ __asm__ volatile (
+ "pxor %%mm6, %%mm6 \n\t" /* deinterlaced pixel counter */
+ "movd %0, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm7 \n\t"
+ "punpcklwd %%mm7, %%mm7 \n\t"
+ "punpckldq %%mm7, %%mm7 \n\t" /* mm7 = threshold */
+ : /* no output */
+ : "rm" (t)
+ );
+ do {
+ __asm__ volatile (
+ "movq (%0), %%mm0\n\t"
+ "movq (%0,%3,2), %%mm1\n\t"
+ "movq %%mm0, (%2)\n\t"
+ "pmaxub %%mm1, %%mm0\n\t"
+ "pavgb (%0), %%mm1\n\t"
+ "psubusb %%mm1, %%mm0\n\t"
+ "paddusb %%mm7, %%mm0\n\t" /* mm0 = max-avg+thr */
+ "movq (%0,%1), %%mm2\n\t"
+ "movq (%0,%5), %%mm3\n\t"
+ "movq %%mm2, %%mm4\n\t"
+ PDIFFUBT(%%mm1, %%mm2, %%mm5)
+ PDIFFUBT(%%mm1, %%mm3, %%mm5)
+ "pminub %%mm2, %%mm3\n\t"
+ "pcmpeqb %%mm3, %%mm2\n\t" /* b = min */
+ "pand %%mm2, %%mm4\n\t"
+ "pandn (%0,%5), %%mm2\n\t"
+ "por %%mm4, %%mm2\n\t"
+ "pminub %%mm0, %%mm3\n\t"
+ "pcmpeqb %%mm0, %%mm3\n\t" /* set to 1s if >= threshold */
+ "psubb %%mm3, %%mm6\n\t" /* count pixels above thr. */
+ "pand %%mm3, %%mm1 \n\t"
+ "pandn %%mm2, %%mm3 \n\t"
+ "por %%mm3, %%mm1 \n\t" /* avg if >= threshold */
+ "movq %%mm1, (%2,%4) \n\t"
+ : /* no output */
+ : "r" (a), "r" ((x86_reg)bos), "r" ((x86_reg)dst), "r" ((x86_reg)ss), "r" ((x86_reg)ds), "r" ((x86_reg)cos)
+ );
+ a += 8;
+ dst += 8;
+ } while (--len);
+
+ __asm__ volatile ("pxor %%mm7, %%mm7 \n\t"
+ "psadbw %%mm6, %%mm7 \n\t"
+ "movd %%mm7, %0 \n\t"
+ "emms \n\t"
+ : "=r" (ret)
+ );
+ return ret;
+#endif
+}
+
+static inline int
+dint_copy_line(unsigned char *dst, unsigned char *a, long bos,
+ long cos, int ds, int ss, int w, int t)
+{
+ unsigned long len = ((unsigned long)w+sizeof(cmmx_t)-1) / sizeof(cmmx_t);
+ cmmx_t dint_count = 0;
+ cmmx_t thr;
+ t |= t << 8;
+ thr = t | (t << 16);
+ if (sizeof(cmmx_t) > 4)
+ thr |= thr << (sizeof(cmmx_t)*4);
+ do {
+ cmmx_t e = *(cmmx_t*)a;
+ cmmx_t ne = *(cmmx_t*)(a+2*ss);
+ cmmx_t o = *(cmmx_t*)(a+bos);
+ cmmx_t oo = *(cmmx_t*)(a+cos);
+ cmmx_t maxe = pmaxub(e, ne);
+ cmmx_t avge = pavgb(e, ne);
+ cmmx_t max_diff = maxe - avge + thr; /* 0<=max-avg<128, thr<128 */
+ cmmx_t diffo = pdiffub(avge, o);
+ cmmx_t diffoo = pdiffub(avge, oo);
+ cmmx_t diffcmp = pcmpgtub(diffo, diffoo);
+ cmmx_t bo = ((oo ^ o) & diffcmp) ^ o;
+ cmmx_t diffbo = ((diffoo ^ diffo) & diffcmp) ^ diffo;
+ cmmx_t above_thr = ~pcmpgtub(max_diff, diffbo);
+ cmmx_t bo_or_avg = ((avge ^ bo) & above_thr) ^ bo;
+ dint_count += above_thr & ONE_BYTES;
+ *(cmmx_t*)(dst) = e;
+ *(cmmx_t*)(dst+ds) = bo_or_avg;
+ a += sizeof(cmmx_t);
+ dst += sizeof(cmmx_t);
+ } while (--len);
+ return psumbw(dint_count);
+}
+
+static int
+dint_copy_plane(unsigned char *d, unsigned char *a, unsigned char *b,
+ unsigned char *c, unsigned long w, unsigned long h,
+ unsigned long ds, unsigned long ss, unsigned long threshold,
+ long field, long mmx2)
+{
+ unsigned long ret = 0;
+ long bos = b - a;
+ long cos = c - a;
+ if (field) {
+ fast_memcpy(d, b, w);
+ h--;
+ d += ds;
+ a += ss;
+ }
+ bos += ss;
+ cos += ss;
+ while (h > 2) {
+ if (threshold >= 128) {
+ fast_memcpy(d, a, w);
+ fast_memcpy(d+ds, a+bos, w);
+ } else if (mmx2 == 1) {
+ ret += dint_copy_line_mmx2(d, a, bos, cos, ds, ss, w, threshold);
+ } else
+ ret += dint_copy_line(d, a, bos, cos, ds, ss, w, threshold);
+ h -= 2;
+ d += 2*ds;
+ a += 2*ss;
+ }
+ fast_memcpy(d, a, w);
+ if (h == 2)
+ fast_memcpy(d+ds, a+bos, w);
+ return ret;
+}
+
+static void
+copy_merge_fields(struct vf_priv_s *p, mp_image_t *dmpi,
+ unsigned char **old, unsigned char **new, unsigned long show)
+{
+ unsigned long threshold = 256;
+ unsigned long field = p->swapped;
+ unsigned long dint_pixels = 0;
+ unsigned char **other = old;
+ if (show >= 12 || !(show & 3))
+ show >>= 2, other = new, new = old;
+ if (show <= 2) { /* Single field: de-interlace */
+ threshold = p->dint_thres;
+ field ^= show & 1;
+ old = new;
+ } else if (show == 3)
+ old = new;
+ else
+ field ^= 1;
+ dint_pixels +=dint_copy_plane(dmpi->planes[0], old[0], new[0],
+ other[0], p->w, p->h, dmpi->stride[0],
+ p->stride, threshold, field, p->mmx2);
+ if (dmpi->flags & MP_IMGFLAG_PLANAR) {
+ if (p->luma_only)
+ old = new, other = new;
+ else
+ threshold = threshold/2 + 1;
+ field ^= p->chroma_swapped;
+ dint_copy_plane(dmpi->planes[1], old[1], new[1],
+ other[1], p->cw, p->ch, dmpi->stride[1],
+ p->chroma_stride, threshold, field, p->mmx2);
+ dint_copy_plane(dmpi->planes[2], old[2], new[2],
+ other[2], p->cw, p->ch, dmpi->stride[2],
+ p->chroma_stride, threshold, field, p->mmx2);
+ }
+ if (dint_pixels > 0 && p->verbose)
+ mp_msg(MSGT_VFILTER,MSGL_INFO,"Deinterlaced %lu pixels\n",dint_pixels);
+}
+
+static void diff_planes(struct vf_priv_s *p, struct frame_stats *s,
+ unsigned char *of, unsigned char *nf,
+ int w, int h, int os, int ns, int swapped)
+{
+ int i, y;
+ int align = -(long)nf & 7;
+ of += align;
+ nf += align;
+ w -= align;
+ if (swapped)
+ of -= os, nf -= ns;
+ i = (h*3 >> 7) & ~1;
+ of += i*os + 8;
+ nf += i*ns + 8;
+ h -= i;
+ w -= 16;
+
+ memset(s, 0, sizeof(*s));
+
+ for (y = (h-8) >> 3; y; y--) {
+ if (p->mmx2 == 1) {
+ for (i = 0; i < w; i += 8)
+ block_metrics_mmx2(of+i, nf+i, os, ns, 4, p, s);
+ } else if (p->mmx2 == 2) {
+ for (i = 0; i < w; i += 8)
+ block_metrics_3dnow(of+i, nf+i, os, ns, 4, p, s);
+ } else if (p->fast > 3) {
+ for (i = 0; i < w; i += 8)
+ block_metrics_faster_c(of+i, nf+i, os, ns, 4, p, s);
+ } else if (p->fast > 1) {
+ for (i = 0; i < w; i += 8)
+ block_metrics_fast_c(of+i, nf+i, os, ns, 4, p, s);
+ } else {
+ for (i = 0; i < w; i += 8)
+ block_metrics_c(of+i, nf+i, os, ns, 4, p, s);
+ }
+ of += 8*os;
+ nf += 8*ns;
+ }
+}
+
+#define METRICS(X) (X).even, (X).odd, (X).noise, (X).temp
+
+static void diff_fields(struct vf_priv_s *p, struct frame_stats *s,
+ unsigned char **old, unsigned char **new)
+{
+ diff_planes(p, s, old[0], new[0], p->w, p->h,
+ p->stride, p->stride, p->swapped);
+ s->sad.even = (s->sad.even * 16ul) / s->num_blocks;
+ s->sad.odd = (s->sad.odd * 16ul) / s->num_blocks;
+ s->sad.noise = (s->sad.noise * 16ul) / s->num_blocks;
+ s->sad.temp = (s->sad.temp * 16ul) / s->num_blocks;
+ if (p->verbose)
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "%lu%c M:%d/%d/%d/%d - %d, "
+ "t:%d/%d/%d/%d, l:%d/%d/%d/%d, h:%d/%d/%d/%d, bg:%d/%d/%d/%d, "
+ "2x:%d/%d/%d/%d, sad:%d/%d/%d/%d, lil:%d, hil:%d, ios:%.1f\n",
+ p->inframes, p->chflag, METRICS(s->max), s->num_blocks,
+ METRICS(s->tiny), METRICS(s->low), METRICS(s->high),
+ METRICS(s->bigger), METRICS(s->twox), METRICS(s->sad),
+ s->interlaced_low, s->interlaced_high,
+ p->iosync / (double) p->in_inc);
+}
+
+static const char *parse_args(struct vf_priv_s *p, const char *args)
+{
+ args--;
+ while (args && *++args &&
+ (sscanf(args, "io=%lu:%lu", &p->out_dec, &p->in_inc) == 2 ||
+ sscanf(args, "diff_thres=%hu", &p->thres.even ) == 1 ||
+ sscanf(args, "comb_thres=%hu", &p->thres.noise) == 1 ||
+ sscanf(args, "sad_thres=%lu", &p->sad_thres ) == 1 ||
+ sscanf(args, "dint_thres=%lu", &p->dint_thres ) == 1 ||
+ sscanf(args, "fast=%u", &p->fast ) == 1 ||
+ sscanf(args, "mmx2=%lu", &p->mmx2 ) == 1 ||
+ sscanf(args, "luma_only=%u", &p->luma_only ) == 1 ||
+ sscanf(args, "verbose=%u", &p->verbose ) == 1 ||
+ sscanf(args, "crop=%lu:%lu:%lu:%lu", &p->w,
+ &p->h, &p->crop_x, &p->crop_y) == 4))
+ args = strchr(args, '/');
+ return args;
+}
+
+static unsigned long gcd(unsigned long x, unsigned long y)
+{
+ unsigned long t;
+ if (x > y)
+ t = x, x = y, y = t;
+
+ while (x) {
+ t = y % x;
+ y = x;
+ x = t;
+ }
+ return y;
+}
+
+static void init(struct vf_priv_s *p, mp_image_t *mpi)
+{
+ unsigned long i;
+ unsigned long plane_size, chroma_plane_size;
+ unsigned char *plane;
+ unsigned long cos, los;
+ p->crop_cx = p->crop_x >> mpi->chroma_x_shift;
+ p->crop_cy = p->crop_y >> mpi->chroma_y_shift;
+ if (mpi->flags & MP_IMGFLAG_ACCEPT_STRIDE) {
+ p->stride = (mpi->w + 15) & ~15;
+ p->chroma_stride = p->stride >> mpi->chroma_x_shift;
+ } else {
+ p->stride = mpi->width;
+ p->chroma_stride = mpi->chroma_width;
+ }
+ p->cw = p->w >> mpi->chroma_x_shift;
+ p->ch = p->h >> mpi->chroma_y_shift;
+ p->nplanes = 1;
+ p->static_idx = 0;
+ p->temp_idx = 0;
+ p->old_planes = p->planes[0];
+ plane_size = mpi->h * p->stride;
+ chroma_plane_size = mpi->flags & MP_IMGFLAG_PLANAR ?
+ mpi->chroma_height * p->chroma_stride : 0;
+ p->memory_allocated =
+ malloc(NUM_STORED * (plane_size+2*chroma_plane_size) +
+ 8*p->chroma_stride + 4096);
+ /* align to page boundary */
+ plane = p->memory_allocated + (-(long)p->memory_allocated & 4095);
+ memset(plane, 0, NUM_STORED * plane_size);
+ los = p->crop_x + p->crop_y * p->stride;
+ cos = p->crop_cx + p->crop_cy * p->chroma_stride;
+ for (i = 0; i != NUM_STORED; i++, plane += plane_size) {
+ p->planes[i][0] = plane;
+ p->planes[NUM_STORED + i][0] = plane + los;
+ }
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ p->nplanes = 3;
+ memset(plane, 0x80, NUM_STORED * 2 * chroma_plane_size);
+ for (i = 0; i != NUM_STORED; i++) {
+ p->planes[i][1] = plane;
+ p->planes[NUM_STORED + i][1] = plane + cos;
+ plane += chroma_plane_size;
+ p->planes[i][2] = plane;
+ p->planes[NUM_STORED + i][2] = plane + cos;
+ plane += chroma_plane_size;
+ }
+ }
+ p->out_dec <<= 2;
+ i = gcd(p->in_inc, p->out_dec);
+ p->in_inc /= i;
+ p->out_dec /= i;
+ p->iosync = 0;
+ p->num_fields = 3;
+}
+
+static inline double get_time(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return tv.tv_sec + tv.tv_usec * 1e-6;
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi)
+{
+ struct vf_priv_s *p = vf->priv;
+ static unsigned char **planes, planes_idx;
+
+ if (mpi->type == MP_IMGTYPE_STATIC) return;
+
+ if (!p->planes[0][0]) init(p, mpi);
+
+ if (mpi->type == MP_IMGTYPE_TEMP ||
+ (mpi->type == MP_IMGTYPE_IPB && !(mpi->flags & MP_IMGFLAG_READABLE)))
+ planes_idx = NUM_STORED/2 + (++p->temp_idx % (NUM_STORED/2));
+ else
+ planes_idx = ++p->static_idx % (NUM_STORED/2);
+ planes = p->planes[planes_idx];
+ mpi->priv = p->planes[NUM_STORED + planes_idx];
+ if (mpi->priv == p->old_planes) {
+ unsigned char **old_planes =
+ p->planes[NUM_STORED + 2 + (++p->temp_idx & 1)];
+ my_memcpy_pic(old_planes[0], p->old_planes[0],
+ p->w, p->h, p->stride, p->stride);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(old_planes[1], p->old_planes[1],
+ p->cw, p->ch, p->chroma_stride, p->chroma_stride);
+ my_memcpy_pic(old_planes[2], p->old_planes[2],
+ p->cw, p->ch, p->chroma_stride, p->chroma_stride);
+ }
+ p->old_planes = old_planes;
+ p->num_copies++;
+ }
+ mpi->planes[0] = planes[0];
+ mpi->stride[0] = p->stride;
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ mpi->planes[1] = planes[1];
+ mpi->planes[2] = planes[2];
+ mpi->stride[1] = mpi->stride[2] = p->chroma_stride;
+ }
+ mpi->width = p->stride;
+
+ mpi->flags |= MP_IMGFLAG_DIRECT;
+ mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
+}
+
+static inline long
+cmpe(unsigned long x, unsigned long y, unsigned long err, unsigned long e)
+{
+ long diff = x-y;
+ long unit = ((x+y+err) >> e);
+ long ret = (diff > unit) - (diff < -unit);
+ unit >>= 1;
+ return ret + (diff > unit) - (diff < -unit);
+}
+
+static unsigned long
+find_breaks(struct vf_priv_s *p, struct frame_stats *s)
+{
+ struct frame_stats *ps = &p->stats[(p->inframes-1) & 1];
+ long notfilm = 5*p->in_inc - p->out_dec;
+ unsigned long n = s->num_blocks >> 8;
+ unsigned long sad_comb_cmp = cmpe(s->sad.temp, s->sad.noise, 512, 1);
+ unsigned long ret = 8;
+
+ if (cmpe(s->sad.temp, s->sad.even, 512, 1) > 0)
+ mp_msg(MSGT_VFILTER, MSGL_WARN,
+ "@@@@@@@@ Bottom-first field??? @@@@@@@@\n");
+ if (s->sad.temp > 1000 && s->sad.noise > 1000)
+ return 3;
+ if (s->interlaced_high >= 2*n && s->sad.temp > 256 && s->sad.noise > 256)
+ return 3;
+ if (s->high.noise > s->num_blocks/4 && s->sad.noise > 10000 &&
+ s->sad.noise > 2*s->sad.even && s->sad.noise > 2*ps->sad.odd) {
+ // Mid-frame scene change
+ if (s->tiny.temp + s->interlaced_low < n ||
+ s->low.temp + s->interlaced_high < n/4 ||
+ s->high.temp + s->interlaced_high < n/8 ||
+ s->sad.temp < 160)
+ return 1;
+ return 3;
+ }
+ if (s->high.temp > s->num_blocks/4 && s->sad.temp > 10000 &&
+ s->sad.temp > 2*ps->sad.odd && s->sad.temp > 2*ps->sad.even) {
+ // Start frame scene change
+ if (s->tiny.noise + s->interlaced_low < n ||
+ s->low.noise + s->interlaced_high < n/4 ||
+ s->high.noise + s->interlaced_high < n/8 ||
+ s->sad.noise < 160)
+ return 2;
+ return 3;
+ }
+ if (sad_comb_cmp == 2)
+ return 2;
+ if (sad_comb_cmp == -2)
+ return 1;
+
+ if (s->tiny.odd > 3*MAX(n,s->tiny.even) + s->interlaced_low)
+ return 1;
+ if (s->tiny.even > 3*MAX(n,s->tiny.odd)+s->interlaced_low &&
+ (!sad_comb_cmp || (s->low.noise <= n/4 && s->low.temp <= n/4)))
+ return 4;
+
+ if (s->sad.noise < 64 && s->sad.temp < 64 &&
+ s->low.noise <= n/2 && s->high.noise <= n/4 &&
+ s->low.temp <= n/2 && s->high.temp <= n/4)
+ goto still;
+
+ if (s->tiny.temp > 3*MAX(n,s->tiny.noise) + s->interlaced_low)
+ return 2;
+ if (s->tiny.noise > 3*MAX(n,s->tiny.temp) + s->interlaced_low)
+ return 1;
+
+ if (s->low.odd > 3*MAX(n/4,s->low.even) + s->interlaced_high)
+ return 1;
+ if (s->low.even > 3*MAX(n/4,s->low.odd)+s->interlaced_high &&
+ s->sad.even > 2*s->sad.odd &&
+ (!sad_comb_cmp || (s->low.noise <= n/4 && s->low.temp <= n/4)))
+ return 4;
+
+ if (s->low.temp > 3*MAX(n/4,s->low.noise) + s->interlaced_high)
+ return 2;
+ if (s->low.noise > 3*MAX(n/4,s->low.temp) + s->interlaced_high)
+ return 1;
+
+ if (sad_comb_cmp == 1 && s->sad.noise < 64)
+ return 2;
+ if (sad_comb_cmp == -1 && s->sad.temp < 64)
+ return 1;
+
+ if (s->tiny.odd <= n || (s->tiny.noise <= n/2 && s->tiny.temp <= n/2)) {
+ if (s->interlaced_low <= n) {
+ if (p->num_fields == 1)
+ goto still;
+ if (s->tiny.even <= n || ps->tiny.noise <= n/2)
+ /* Still frame */
+ goto still;
+ if (s->bigger.even >= 2*MAX(n,s->bigger.odd) + s->interlaced_low)
+ return 4;
+ if (s->low.even >= 2*n + s->interlaced_low)
+ return 4;
+ goto still;
+ }
+ }
+ if (s->low.odd <= n/4) {
+ if (s->interlaced_high <= n/4) {
+ if (p->num_fields == 1)
+ goto still;
+ if (s->low.even <= n/4)
+ /* Still frame */
+ goto still;
+ if (s->bigger.even >= 2*MAX(n/4,s->bigger.odd)+s->interlaced_high)
+ return 4;
+ if (s->low.even >= n/2 + s->interlaced_high)
+ return 4;
+ goto still;
+ }
+ }
+ if (s->bigger.temp > 2*MAX(n,s->bigger.noise) + s->interlaced_low)
+ return 2;
+ if (s->bigger.noise > 2*MAX(n,s->bigger.temp) + s->interlaced_low)
+ return 1;
+ if (s->bigger.temp > 2*MAX(n,s->bigger.noise) + s->interlaced_high)
+ return 2;
+ if (s->bigger.noise > 2*MAX(n,s->bigger.temp) + s->interlaced_high)
+ return 1;
+ if (s->twox.temp > 2*MAX(n,s->twox.noise) + s->interlaced_high)
+ return 2;
+ if (s->twox.noise > 2*MAX(n,s->twox.temp) + s->interlaced_high)
+ return 1;
+ if (s->bigger.even > 2*MAX(n,s->bigger.odd) + s->interlaced_low &&
+ s->bigger.temp < n && s->bigger.noise < n)
+ return 4;
+ if (s->interlaced_low > MIN(2*n, s->tiny.odd))
+ return 3;
+ ret = 8 + (1 << (s->sad.temp > s->sad.noise));
+ still:
+ if (p->num_fields == 1 && p->prev_fields == 3 && notfilm >= 0 &&
+ (s->tiny.temp <= s->tiny.noise || s->sad.temp < s->sad.noise+16))
+ return 1;
+ if (p->notout < p->num_fields && p->iosync > 2*p->in_inc && notfilm < 0)
+ notfilm = 0;
+ if (p->num_fields < 2 ||
+ (p->num_fields == 2 && p->prev_fields == 2 && notfilm < 0))
+ return ret;
+ if (!notfilm && (p->prev_fields&~1) == 2) {
+ if (p->prev_fields + p->num_fields == 5) {
+ if (s->tiny.noise <= s->tiny.temp ||
+ s->low.noise == 0 || s->low.noise < s->low.temp ||
+ s->sad.noise < s->sad.temp+16)
+ return 2;
+ }
+ if (p->prev_fields + p->num_fields == 4) {
+ if (s->tiny.temp <= s->tiny.noise ||
+ s->low.temp == 0 || s->low.temp < s->low.noise ||
+ s->sad.temp < s->sad.noise+16)
+ return 1;
+ }
+ }
+ if (p->num_fields > 2 &&
+ ps->sad.noise > s->sad.noise && ps->sad.noise > s->sad.temp)
+ return 4;
+ return 2 >> (s->sad.noise > s->sad.temp);
+}
+
+#define ITOC(X) (!(X) ? ' ' : (X) + ((X)>9 ? 'a'-10 : '0'))
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+ struct vf_priv_s *p = vf->priv;
+ unsigned char **planes, **old_planes;
+ struct frame_stats *s = &p->stats[p->inframes & 1];
+ struct frame_stats *ps = &p->stats[(p->inframes-1) & 1];
+ int swapped = 0;
+ const int flags = mpi->fields;
+ int breaks, prev;
+ int show_fields = 0;
+ int dropped_fields = 0;
+ double start_time, diff_time;
+ char prev_chflag = p->chflag;
+ int keep_rate;
+
+ if (!p->planes[0][0]) init(p, mpi);
+
+ old_planes = p->old_planes;
+
+ if ((mpi->flags & MP_IMGFLAG_DIRECT) && mpi->priv) {
+ planes = mpi->priv;
+ mpi->priv = 0;
+ } else {
+ planes = p->planes[2 + (++p->temp_idx & 1)];
+ my_memcpy_pic(planes[0],
+ mpi->planes[0] + p->crop_x + p->crop_y * mpi->stride[0],
+ p->w, p->h, p->stride, mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(planes[1],
+ mpi->planes[1] + p->crop_cx + p->crop_cy * mpi->stride[1],
+ p->cw, p->ch, p->chroma_stride, mpi->stride[1]);
+ my_memcpy_pic(planes[2],
+ mpi->planes[2] + p->crop_cx + p->crop_cy * mpi->stride[2],
+ p->cw, p->ch, p->chroma_stride, mpi->stride[2]);
+ p->num_copies++;
+ }
+ }
+
+ p->old_planes = planes;
+ p->chflag = ';';
+ if (flags & MP_IMGFIELD_ORDERED) {
+ swapped = !(flags & MP_IMGFIELD_TOP_FIRST);
+ p->chflag = (flags & MP_IMGFIELD_REPEAT_FIRST ? '|' :
+ flags & MP_IMGFIELD_TOP_FIRST ? ':' : '.');
+ }
+ p->swapped = swapped;
+
+ start_time = get_time();
+ if (p->chflag == '|') {
+ *s = ppzs;
+ p->iosync += p->in_inc;
+ } else if ((p->fast & 1) && prev_chflag == '|')
+ *s = pprs;
+ else
+ diff_fields(p, s, old_planes, planes);
+ diff_time = get_time();
+ p->diff_time += diff_time - start_time;
+ breaks = p->inframes ? find_breaks(p, s) : 2;
+ p->inframes++;
+ keep_rate = 4*p->in_inc == p->out_dec;
+
+ switch (breaks) {
+ case 0:
+ case 8:
+ case 9:
+ case 10:
+ if (!keep_rate && p->notout < p->num_fields && p->iosync < 2*p->in_inc)
+ break;
+ if (p->notout < p->num_fields)
+ dropped_fields = -2;
+ case 4:
+ if (keep_rate || p->iosync >= -2*p->in_inc)
+ show_fields = (4<<p->num_fields)-1;
+ break;
+ case 3:
+ if (keep_rate)
+ show_fields = 2;
+ else if (p->iosync > 0) {
+ if (p->notout >= p->num_fields && p->iosync > 2*p->in_inc) {
+ show_fields = 4; /* prev odd only */
+ if (p->num_fields > 1)
+ show_fields |= 8; /* + prev even */
+ } else {
+ show_fields = 2; /* even only */
+ if (p->notout >= p->num_fields)
+ dropped_fields += p->num_fields;
+ }
+ }
+ break;
+ case 2:
+ if (p->iosync <= -3*p->in_inc) {
+ if (p->notout >= p->num_fields)
+ dropped_fields = p->num_fields;
+ break;
+ }
+ if (p->num_fields == 1) {
+ int prevbreak = ps->sad.noise >= 128;
+ if (p->iosync < 4*p->in_inc) {
+ show_fields = 3;
+ dropped_fields = prevbreak;
+ } else {
+ show_fields = 4 | (!prevbreak << 3);
+ if (p->notout < 1 + p->prev_fields)
+ dropped_fields = -!prevbreak;
+ }
+ break;
+ }
+ default:
+ if (keep_rate)
+ show_fields = 3 << (breaks & 1);
+ else if (p->notout >= p->num_fields &&
+ p->iosync >= (breaks == 1 ? -p->in_inc :
+ p->in_inc << (p->num_fields == 1))) {
+ show_fields = (1 << (2 + p->num_fields)) - (1<<breaks);
+ } else {
+ if (p->notout >= p->num_fields)
+ dropped_fields += p->num_fields + 2 - breaks;
+ if (breaks == 1) {
+ if (p->iosync >= 4*p->in_inc)
+ show_fields = 6;
+ } else if (p->iosync > -3*p->in_inc)
+ show_fields = 3; /* odd+even */
+ }
+ break;
+ }
+
+ show_fields &= 15;
+ prev = p->prev_fields;
+ if (breaks < 8) {
+ if (p->num_fields == 1)
+ breaks &= ~4;
+ if (breaks)
+ p->num_breaks++;
+ if (breaks == 3)
+ p->prev_fields = p->num_fields = 1;
+ else if (breaks) {
+ p->prev_fields = p->num_fields + (breaks==1) - (breaks==4);
+ p->num_fields = breaks - (breaks == 4) + (p->chflag == '|');
+ } else
+ p->num_fields += 2;
+ } else
+ p->num_fields += 2;
+
+ p->iosync += 4 * p->in_inc;
+ if (p->chflag == '|')
+ p->iosync += p->in_inc;
+
+ if (show_fields) {
+ p->iosync -= p->out_dec;
+ p->notout = !(show_fields & 1) + !(show_fields & 3);
+ if (((show_fields & 3) == 3 &&
+ (s->low.noise + s->interlaced_low < (s->num_blocks>>8) ||
+ s->sad.noise < 160)) ||
+ ((show_fields & 12) == 12 &&
+ (ps->low.noise + ps->interlaced_low < (s->num_blocks>>8) ||
+ ps->sad.noise < 160))) {
+ p->export_count++;
+ dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT,
+ MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE,
+ p->w, p->h);
+ if ((show_fields & 3) != 3) planes = old_planes;
+ dmpi->planes[0] = planes[0];
+ dmpi->stride[0] = p->stride;
+ dmpi->width = mpi->width;
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ dmpi->planes[1] = planes[1];
+ dmpi->planes[2] = planes[2];
+ dmpi->stride[1] = p->chroma_stride;
+ dmpi->stride[2] = p->chroma_stride;
+ }
+ } else {
+ p->merge_count++;
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ p->w, p->h);
+ copy_merge_fields(p, dmpi, old_planes, planes, show_fields);
+ }
+ p->outframes++;
+ } else
+ p->notout += 2;
+
+ if (p->verbose)
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "%lu %lu: %x %c %c %lu%s%s%c%s\n",
+ p->inframes, p->outframes,
+ breaks, breaks<8 && breaks>0 ? (int) p->prev_fields+'0' : ' ',
+ ITOC(show_fields),
+ p->num_breaks, 5*p->in_inc == p->out_dec && breaks<8 &&
+ breaks>0 && ((prev&~1)!=2 || prev+p->prev_fields!=5) ?
+ " ######## bad telecine ########" : "",
+ dropped_fields ? " ======== dropped ":"", ITOC(dropped_fields),
+ !show_fields || (show_fields & (show_fields-1)) ?
+ "" : " @@@@@@@@@@@@@@@@@");
+
+ p->merge_time += get_time() - diff_time;
+ return show_fields ? vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) : 0;
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - support more formats */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ case IMGFMT_411P:
+ case IMGFMT_422P:
+ case IMGFMT_444P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ unsigned long cxm = 0;
+ unsigned long cym = 0;
+ struct vf_priv_s *p = vf->priv;
+ // rounding:
+ if(!IMGFMT_IS_RGB(outfmt) && !IMGFMT_IS_BGR(outfmt)){
+ switch(outfmt){
+ case IMGFMT_444P:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ break;
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ cym = 3;
+ case IMGFMT_411P:
+ cxm = 3;
+ break;
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ cym = 1;
+ default:
+ cxm = 1;
+ }
+ }
+ p->chroma_swapped = !!(p->crop_y & (cym+1));
+ if (p->w) p->w += p->crop_x & cxm;
+ if (p->h) p->h += p->crop_y & cym;
+ p->crop_x &= ~cxm;
+ p->crop_y &= ~cym;
+ if (!p->w || p->w > width ) p->w = width;
+ if (!p->h || p->h > height) p->h = height;
+ if (p->crop_x + p->w > width ) p->crop_x = 0;
+ if (p->crop_y + p->h > height) p->crop_y = 0;
+
+ if(!opt_screen_size_x && !opt_screen_size_y){
+ d_width = d_width * p->w/width;
+ d_height = d_height * p->h/height;
+ }
+ return vf_next_config(vf, p->w, p->h, d_width, d_height, flags, outfmt);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ struct vf_priv_s *p = vf->priv;
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "diff_time: %.3f, merge_time: %.3f, "
+ "export: %lu, merge: %lu, copy: %lu\n", p->diff_time, p->merge_time,
+ p->export_count, p->merge_count, p->num_copies);
+ free(p->memory_allocated);
+ free(p);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ vf->get_image = get_image;
+ vf->put_image = put_image;
+ vf->config = config;
+ vf->query_format = query_format;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ p->out_dec = 5;
+ p->in_inc = 4;
+ p->thres.noise = 128;
+ p->thres.even = 128;
+ p->sad_thres = 64;
+ p->dint_thres = 4;
+ p->luma_only = 0;
+ p->fast = 3;
+ p->mmx2 = gCpuCaps.hasMMX2 ? 1 : gCpuCaps.has3DNow ? 2 : 0;
+ if (args) {
+ const char *args_remain = parse_args(p, args);
+ if (args_remain) {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL,
+ "filmdint: unknown suboption: %s\n", args_remain);
+ return 0;
+ }
+ if (p->out_dec < p->in_inc) {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL,
+ "filmdint: increasing the frame rate is not supported\n");
+ return 0;
+ }
+ }
+ if (p->mmx2 > 2)
+ p->mmx2 = 0;
+#if !HAVE_MMX
+ p->mmx2 = 0;
+#endif
+#if !HAVE_AMD3DNOW
+ p->mmx2 &= 1;
+#endif
+ p->thres.odd = p->thres.even;
+ p->thres.temp = p->thres.noise;
+ p->diff_time = 0;
+ p->merge_time = 0;
+ return 1;
+}
+
+const vf_info_t vf_info_filmdint = {
+ "Advanced inverse telecine filer",
+ "filmdint",
+ "Zoltan Hidvegi",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_fixpts.c b/libavfilter/libmpcodecs/vf_fixpts.c
new file mode 100644
index 0000000000..ae32b40d83
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_fixpts.c
@@ -0,0 +1,137 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ double current;
+ double step;
+ int autostart;
+ int autostep;
+ unsigned have_step:1;
+ unsigned print:1;
+};
+
+static int put_image(vf_instance_t *vf, mp_image_t *src, double pts)
+{
+ struct vf_priv_s *p = vf->priv;
+
+ if (p->print) {
+ if (pts == MP_NOPTS_VALUE)
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "PTS: undef\n");
+ else
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "PTS: %f\n", pts);
+ }
+ if (pts != MP_NOPTS_VALUE && p->autostart != 0) {
+ p->current = pts;
+ if (p->autostart > 0)
+ p->autostart--;
+ } else if (pts != MP_NOPTS_VALUE && p->autostep > 0) {
+ p->step = pts - p->current;
+ p->current = pts;
+ p->autostep--;
+ p->have_step = 1;
+ } else if (p->have_step) {
+ p->current += p->step;
+ pts = p->current;
+ } else {
+ pts = MP_NOPTS_VALUE;
+ }
+ return vf_next_put_image(vf, src, pts);
+}
+
+static void uninit(vf_instance_t *vf)
+{
+ free(vf->priv);
+}
+
+static int parse_args(struct vf_priv_s *p, const char *args)
+{
+ int pos;
+ double num, denom = 1;
+ int iarg;
+
+ while (*args != 0) {
+ pos = 0;
+ if (sscanf(args, "print%n", &pos) == 0 && pos > 0) {
+ p->print = 1;
+ } else if (sscanf(args, "fps=%lf%n/%lf%n", &num, &pos, &denom, &pos) >=
+ 1 && pos > 0) {
+ p->step = denom / num;
+ p->have_step = 1;
+ } else if (sscanf(args, "start=%lf%n", &num, &pos) >= 1 && pos > 0) {
+ p->current = num;
+ } else if (sscanf(args, "autostart=%d%n", &iarg, &pos) == 1 && pos > 0) {
+ p->autostart = iarg;
+ } else if (sscanf(args, "autofps=%d%n", &iarg, &pos) == 1 && pos > 0) {
+ p->autostep = iarg;
+ } else {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL,
+ "fixpts: unknown suboption: %s\n", args);
+ return 0;
+ }
+ args += pos;
+ if (*args == ':')
+ args++;
+ }
+ return 1;
+}
+
+static int open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ struct vf_priv_s ptmp = {
+ .current = 0,
+ .step = 0,
+ .autostart = 0,
+ .autostep = 0,
+ .have_step = 0,
+ .print = 0,
+ };
+
+ if (!parse_args(&ptmp, args == NULL ? "" : args))
+ return 0;
+
+ vf->put_image = put_image;
+ vf->uninit = uninit;
+ vf->priv = p = malloc(sizeof(struct vf_priv_s));
+ *p = ptmp;
+ p->current = -p->step;
+
+ return 1;
+}
+
+const vf_info_t vf_info_fixpts = {
+ "Fix presentation timestamps",
+ "fixpts",
+ "Nicolas George",
+ "",
+ &open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_framestep.c b/libavfilter/libmpcodecs/vf_framestep.c
new file mode 100644
index 0000000000..cdf5386670
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_framestep.c
@@ -0,0 +1,205 @@
+/*
+ * filter to ouput only 1 every n frame, or only the I (key)frame
+ *
+ * The parameters are:
+ *
+ * [I] | [i]num
+ *
+ * if you call the filter with I (uppercase) as the parameter
+ * ... -vf framestep=I ...
+ * then ONLY the keyframes are outputted.
+ * For DVD it means, generally, one every 15 frames (IBBPBBPBBPBBPBB), for avi it means
+ * every scene change or every keyint value (see -lavcopts).
+ *
+ * if you call the filter with the i (lowercase)
+ * ... -vf framestep=i ...
+ * then a I! followed by a cr is printed when a key frame (eg Intra frame) is
+ * found, leaving the current line of mplayer/mencoder, where you got the
+ * time, in seconds, and frame of the key. Use this information to split the
+ * AVI.
+ *
+ * After the i or alone you can put a positive number and only one frame every
+ * x (the number you set) is passed on the filter chain, limiting the output
+ * of the frame.
+ *
+ * Example
+ * ... -vf framestep=i20 ...
+ * Dump one every 20 frames, printing on the console when a I-Frame is encounter.
+ *
+ * ... -vf framestep=25
+ * Dump one every 25 frames.
+ *
+ * If you call the filter without parameter it does nothing (except using memory
+ * and resource of your system,. of course).
+ *
+ * This filter doesn' t work like the option -sstep seconds.
+ *
+ * The -sstep seek to the new position, without decoding all frames but,
+ * expecially on avi file coded whith mpeg4 (lavc or xvid or divx), the
+ * seek is not always too much precise.
+ *
+ * This filter simply discard the unwanted frames, so you are very precise in
+ * counting the frame but sometime you use a lot of CPU for nothing.
+ *
+ * As usual it depends on what you're doing.
+ *
+ * copyright (c) 2003 Daniele Forghieri ( guru@digitalfantasy.it )
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+/* Uncomment if you want to print some info on the format */
+// #define DUMP_FORMAT_DATA
+
+/* Private data */
+struct vf_priv_s {
+ /* Current frame */
+ int frame_cur;
+ /* Frame output step, 0 = all */
+ int frame_step;
+ /* Only I-Frame (2), print on I-Frame (1) */
+ int dump_iframe;
+};
+
+/* Filter handler */
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+ struct vf_priv_s *priv;
+ int skip;
+
+ priv = vf->priv;
+
+ /* Print the 'I' if is a intra frame. The \n advance the current line so you got the
+ * current file time (in second) and the frame number on the console ;-)
+ */
+ if (priv->dump_iframe) {
+ if (mpi->pict_type == 1) {
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "I!\n");
+ }
+ }
+
+ /* decide if frame must be shown */
+ if (priv->dump_iframe == 2) {
+ /* Only key frame */
+ skip = mpi->pict_type == 1 ? 0 : 1;
+ }
+ else {
+ /* Only 1 every frame_step */
+ skip = 0;
+ if ((priv->frame_step != 0) && ((priv->frame_cur % priv->frame_step) != 0)) {
+ skip = 1;
+ }
+ }
+ /* Increment current frame */
+ ++priv->frame_cur;
+
+ if (skip == 0) {
+ /* Get image, export type (we don't modify tghe image) */
+ dmpi=vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, 0,
+ mpi->w, mpi->h);
+ /* Copy only the pointer ( MP_IMGTYPE_EXPORT ! ) */
+ dmpi->planes[0] = mpi->planes[0];
+ dmpi->planes[1] = mpi->planes[1];
+ dmpi->planes[2] = mpi->planes[2];
+
+ dmpi->stride[0] = mpi->stride[0];
+ dmpi->stride[1] = mpi->stride[1];
+ dmpi->stride[2] = mpi->stride[2];
+
+ dmpi->width = mpi->width;
+ dmpi->height = mpi->height;
+
+ /* Chain to next filter / output ... */
+ return vf_next_put_image(vf, dmpi, pts);
+ }
+
+ /* Skip the frame */
+ return 0;
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ /* Free private data */
+ free(vf->priv);
+}
+
+/* Main entry funct for the filter */
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+
+ vf->put_image = put_image;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ if (p == NULL) {
+ return 0;
+ }
+
+ if (args != NULL) {
+#ifdef DUMP_FORMAT_DATA
+ if (*args == 'd') {
+ p->dump_iframe = 3;
+ }
+ else
+#endif
+ if (*args == 'I') {
+ /* Dump only KEY (ie INTRA) frame */
+ p->dump_iframe = 2;
+ }
+ else {
+ if (*args == 'i') {
+ /* Print a 'I!' when a i-frame is encounter */
+ p->dump_iframe = 1;
+ ++args;
+ }
+
+ if (*args != '\0') {
+ p->frame_step = atoi(args);
+ if (p->frame_step <= 0) {
+ mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_ErrorParsingArgument);
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+const vf_info_t vf_info_framestep = {
+ "Dump one every n / key frames",
+ "framestep",
+ "Daniele Forghieri",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_fspp.c b/libavfilter/libmpcodecs/vf_fspp.c
new file mode 100644
index 0000000000..a98c70b26c
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_fspp.c
@@ -0,0 +1,2117 @@
+/*
+ * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (C) 2005 Nikolaj Poroshin <porosh3@psu.ru>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * This implementation is based on an algorithm described in
+ * "Aria Nosratinia Embedded Post-Processing for
+ * Enhancement of Compressed Images (1999)"
+ * (http://citeseer.nj.nec.com/nosratinia99embedded.html)
+ * Futher, with splitting (i)dct into hor/ver passes, one of them can be
+ * performed once per block, not pixel. This allows for much better speed.
+ */
+
+/*
+ Heavily optimized version of SPP filter by Nikolaj
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "vd_ffmpeg.h"
+#include "libvo/fastmemcpy.h"
+
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+#include "libavcodec/avcodec.h"
+#include "libavcodec/dsputil.h"
+
+#undef free
+#undef malloc
+
+//===========================================================================//
+#define BLOCKSZ 12
+
+static const short custom_threshold[64]=
+// values (296) can't be too high
+// -it causes too big quant dependence
+// or maybe overflow(check), which results in some flashing
+{ 71, 296, 295, 237, 71, 40, 38, 19,
+ 245, 193, 185, 121, 102, 73, 53, 27,
+ 158, 129, 141, 107, 97, 73, 50, 26,
+ 102, 116, 109, 98, 82, 66, 45, 23,
+ 71, 94, 95, 81, 70, 56, 38, 20,
+ 56, 77, 74, 66, 56, 44, 30, 15,
+ 38, 53, 50, 45, 38, 30, 21, 11,
+ 20, 27, 26, 23, 20, 15, 11, 5
+};
+
+static const uint8_t __attribute__((aligned(32))) dither[8][8]={
+ { 0, 48, 12, 60, 3, 51, 15, 63, },
+ { 32, 16, 44, 28, 35, 19, 47, 31, },
+ { 8, 56, 4, 52, 11, 59, 7, 55, },
+ { 40, 24, 36, 20, 43, 27, 39, 23, },
+ { 2, 50, 14, 62, 1, 49, 13, 61, },
+ { 34, 18, 46, 30, 33, 17, 45, 29, },
+ { 10, 58, 6, 54, 9, 57, 5, 53, },
+ { 42, 26, 38, 22, 41, 25, 37, 21, },
+};
+
+struct vf_priv_s { //align 16 !
+ uint64_t threshold_mtx_noq[8*2];
+ uint64_t threshold_mtx[8*2];//used in both C & MMX (& later SSE2) versions
+
+ int log2_count;
+ int temp_stride;
+ int qp;
+ int mpeg2;
+ int prev_q;
+ uint8_t *src;
+ int16_t *temp;
+ int bframes;
+ char *non_b_qp;
+};
+
+
+#if !HAVE_MMX
+
+//This func reads from 1 slice, 1 and clears 0 & 1
+static void store_slice_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)
+{int y, x;
+#define STORE(pos) \
+ temp= (src[x + pos] + (d[pos]>>log2_scale))>>(6-log2_scale); \
+ src[x + pos]=src[x + pos - 8*src_stride]=0; \
+ if(temp & 0x100) temp= ~(temp>>31); \
+ dst[x + pos]= temp;
+
+ for(y=0; y<height; y++){
+ const uint8_t *d= dither[y];
+ for(x=0; x<width; x+=8){
+ int temp;
+ STORE(0);
+ STORE(1);
+ STORE(2);
+ STORE(3);
+ STORE(4);
+ STORE(5);
+ STORE(6);
+ STORE(7);
+ }
+ src+=src_stride;
+ dst+=dst_stride;
+ }
+}
+
+//This func reads from 2 slices, 0 & 2 and clears 2-nd
+static void store_slice2_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)
+{int y, x;
+#define STORE2(pos) \
+ temp= (src[x + pos] + src[x + pos + 16*src_stride] + (d[pos]>>log2_scale))>>(6-log2_scale); \
+ src[x + pos + 16*src_stride]=0; \
+ if(temp & 0x100) temp= ~(temp>>31); \
+ dst[x + pos]= temp;
+
+ for(y=0; y<height; y++){
+ const uint8_t *d= dither[y];
+ for(x=0; x<width; x+=8){
+ int temp;
+ STORE2(0);
+ STORE2(1);
+ STORE2(2);
+ STORE2(3);
+ STORE2(4);
+ STORE2(5);
+ STORE2(6);
+ STORE2(7);
+ }
+ src+=src_stride;
+ dst+=dst_stride;
+ }
+}
+
+static void mul_thrmat_c(struct vf_priv_s *p,int q)
+{
+ int a;
+ for(a=0;a<64;a++)
+ ((short*)p->threshold_mtx)[a]=q * ((short*)p->threshold_mtx_noq)[a];//ints faster in C
+}
+
+static void column_fidct_c(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt);
+static void row_idct_c(DCTELEM* workspace,
+ int16_t* output_adr, int output_stride, int cnt);
+static void row_fdct_c(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt);
+
+//this is rather ugly, but there is no need for function pointers
+#define store_slice_s store_slice_c
+#define store_slice2_s store_slice2_c
+#define mul_thrmat_s mul_thrmat_c
+#define column_fidct_s column_fidct_c
+#define row_idct_s row_idct_c
+#define row_fdct_s row_fdct_c
+
+#else /* HAVE_MMX */
+
+//This func reads from 1 slice, 1 and clears 0 & 1
+static void store_slice_mmx(uint8_t *dst, int16_t *src, long dst_stride, long src_stride, long width, long height, long log2_scale)
+{
+ const uint8_t *od=&dither[0][0];
+ const uint8_t *end=&dither[height][0];
+ width = (width+7)&~7;
+ dst_stride-=width;
+ //src_stride=(src_stride-width)*2;
+ __asm__ volatile(
+ "mov %5, %%"REG_d" \n\t"
+ "mov %6, %%"REG_S" \n\t"
+ "mov %7, %%"REG_D" \n\t"
+ "mov %1, %%"REG_a" \n\t"
+ "movd %%"REG_d", %%mm5 \n\t"
+ "xor $-1, %%"REG_d" \n\t"
+ "mov %%"REG_a", %%"REG_c" \n\t"
+ "add $7, %%"REG_d" \n\t"
+ "neg %%"REG_a" \n\t"
+ "sub %0, %%"REG_c" \n\t"
+ "add %%"REG_c", %%"REG_c" \n\t"
+ "movd %%"REG_d", %%mm2 \n\t"
+ "mov %%"REG_c", %1 \n\t"
+ "mov %2, %%"REG_d" \n\t"
+ "shl $4, %%"REG_a" \n\t"
+
+ "2: \n\t"
+ "movq (%%"REG_d"), %%mm3 \n\t"
+ "movq %%mm3, %%mm4 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "punpckhbw %%mm7, %%mm4 \n\t"
+ "mov %0, %%"REG_c" \n\t"
+ "psraw %%mm5, %%mm3 \n\t"
+ "psraw %%mm5, %%mm4 \n\t"
+ "1: \n\t"
+ "movq %%mm7, (%%"REG_S",%%"REG_a",) \n\t"
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq 8(%%"REG_S"), %%mm1 \n\t"
+
+ "movq %%mm7, 8(%%"REG_S",%%"REG_a",) \n\t"
+ "paddw %%mm3, %%mm0 \n\t"
+ "paddw %%mm4, %%mm1 \n\t"
+
+ "movq %%mm7, (%%"REG_S") \n\t"
+ "psraw %%mm2, %%mm0 \n\t"
+ "psraw %%mm2, %%mm1 \n\t"
+
+ "movq %%mm7, 8(%%"REG_S") \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+ "add $16, %%"REG_S" \n\t"
+
+ "movq %%mm0, (%%"REG_D") \n\t"
+ "add $8, %%"REG_D" \n\t"
+ "sub $8, %%"REG_c" \n\t"
+ "jg 1b \n\t"
+ "add %1, %%"REG_S" \n\t"
+ "add $8, %%"REG_d" \n\t"
+ "add %3, %%"REG_D" \n\t"
+ "cmp %4, %%"REG_d" \n\t"
+ "jl 2b \n\t"
+
+ :
+ : "m" (width), "m" (src_stride), "erm" (od), "m" (dst_stride), "erm" (end),
+ "m" (log2_scale), "m" (src), "m" (dst) //input
+ : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D
+ );
+}
+
+//This func reads from 2 slices, 0 & 2 and clears 2-nd
+static void store_slice2_mmx(uint8_t *dst, int16_t *src, long dst_stride, long src_stride, long width, long height, long log2_scale)
+{
+ const uint8_t *od=&dither[0][0];
+ const uint8_t *end=&dither[height][0];
+ width = (width+7)&~7;
+ dst_stride-=width;
+ //src_stride=(src_stride-width)*2;
+ __asm__ volatile(
+ "mov %5, %%"REG_d" \n\t"
+ "mov %6, %%"REG_S" \n\t"
+ "mov %7, %%"REG_D" \n\t"
+ "mov %1, %%"REG_a" \n\t"
+ "movd %%"REG_d", %%mm5 \n\t"
+ "xor $-1, %%"REG_d" \n\t"
+ "mov %%"REG_a", %%"REG_c" \n\t"
+ "add $7, %%"REG_d" \n\t"
+ "sub %0, %%"REG_c" \n\t"
+ "add %%"REG_c", %%"REG_c" \n\t"
+ "movd %%"REG_d", %%mm2 \n\t"
+ "mov %%"REG_c", %1 \n\t"
+ "mov %2, %%"REG_d" \n\t"
+ "shl $5, %%"REG_a" \n\t"
+
+ "2: \n\t"
+ "movq (%%"REG_d"), %%mm3 \n\t"
+ "movq %%mm3, %%mm4 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "punpckhbw %%mm7, %%mm4 \n\t"
+ "mov %0, %%"REG_c" \n\t"
+ "psraw %%mm5, %%mm3 \n\t"
+ "psraw %%mm5, %%mm4 \n\t"
+ "1: \n\t"
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq 8(%%"REG_S"), %%mm1 \n\t"
+ "paddw %%mm3, %%mm0 \n\t"
+
+ "paddw (%%"REG_S",%%"REG_a",), %%mm0 \n\t"
+ "paddw %%mm4, %%mm1 \n\t"
+ "movq 8(%%"REG_S",%%"REG_a",), %%mm6 \n\t"
+
+ "movq %%mm7, (%%"REG_S",%%"REG_a",) \n\t"
+ "psraw %%mm2, %%mm0 \n\t"
+ "paddw %%mm6, %%mm1 \n\t"
+
+ "movq %%mm7, 8(%%"REG_S",%%"REG_a",) \n\t"
+ "psraw %%mm2, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+
+ "movq %%mm0, (%%"REG_D") \n\t"
+ "add $16, %%"REG_S" \n\t"
+ "add $8, %%"REG_D" \n\t"
+ "sub $8, %%"REG_c" \n\t"
+ "jg 1b \n\t"
+ "add %1, %%"REG_S" \n\t"
+ "add $8, %%"REG_d" \n\t"
+ "add %3, %%"REG_D" \n\t"
+ "cmp %4, %%"REG_d" \n\t"
+ "jl 2b \n\t"
+
+ :
+ : "m" (width), "m" (src_stride), "erm" (od), "m" (dst_stride), "erm" (end),
+ "m" (log2_scale), "m" (src), "m" (dst) //input
+ : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_D, "%"REG_S
+ );
+}
+
+static void mul_thrmat_mmx(struct vf_priv_s *p, int q)
+{
+ uint64_t *adr=&p->threshold_mtx_noq[0];
+ __asm__ volatile(
+ "movd %0, %%mm7 \n\t"
+ "add $8*8*2, %%"REG_D" \n\t"
+ "movq 0*8(%%"REG_S"), %%mm0 \n\t"
+ "punpcklwd %%mm7, %%mm7 \n\t"
+ "movq 1*8(%%"REG_S"), %%mm1 \n\t"
+ "punpckldq %%mm7, %%mm7 \n\t"
+ "pmullw %%mm7, %%mm0 \n\t"
+
+ "movq 2*8(%%"REG_S"), %%mm2 \n\t"
+ "pmullw %%mm7, %%mm1 \n\t"
+
+ "movq 3*8(%%"REG_S"), %%mm3 \n\t"
+ "pmullw %%mm7, %%mm2 \n\t"
+
+ "movq %%mm0, 0*8(%%"REG_D") \n\t"
+ "movq 4*8(%%"REG_S"), %%mm4 \n\t"
+ "pmullw %%mm7, %%mm3 \n\t"
+
+ "movq %%mm1, 1*8(%%"REG_D") \n\t"
+ "movq 5*8(%%"REG_S"), %%mm5 \n\t"
+ "pmullw %%mm7, %%mm4 \n\t"
+
+ "movq %%mm2, 2*8(%%"REG_D") \n\t"
+ "movq 6*8(%%"REG_S"), %%mm6 \n\t"
+ "pmullw %%mm7, %%mm5 \n\t"
+
+ "movq %%mm3, 3*8(%%"REG_D") \n\t"
+ "movq 7*8+0*8(%%"REG_S"), %%mm0 \n\t"
+ "pmullw %%mm7, %%mm6 \n\t"
+
+ "movq %%mm4, 4*8(%%"REG_D") \n\t"
+ "movq 7*8+1*8(%%"REG_S"), %%mm1 \n\t"
+ "pmullw %%mm7, %%mm0 \n\t"
+
+ "movq %%mm5, 5*8(%%"REG_D") \n\t"
+ "movq 7*8+2*8(%%"REG_S"), %%mm2 \n\t"
+ "pmullw %%mm7, %%mm1 \n\t"
+
+ "movq %%mm6, 6*8(%%"REG_D") \n\t"
+ "movq 7*8+3*8(%%"REG_S"), %%mm3 \n\t"
+ "pmullw %%mm7, %%mm2 \n\t"
+
+ "movq %%mm0, 7*8+0*8(%%"REG_D") \n\t"
+ "movq 7*8+4*8(%%"REG_S"), %%mm4 \n\t"
+ "pmullw %%mm7, %%mm3 \n\t"
+
+ "movq %%mm1, 7*8+1*8(%%"REG_D") \n\t"
+ "movq 7*8+5*8(%%"REG_S"), %%mm5 \n\t"
+ "pmullw %%mm7, %%mm4 \n\t"
+
+ "movq %%mm2, 7*8+2*8(%%"REG_D") \n\t"
+ "movq 7*8+6*8(%%"REG_S"), %%mm6 \n\t"
+ "pmullw %%mm7, %%mm5 \n\t"
+
+ "movq %%mm3, 7*8+3*8(%%"REG_D") \n\t"
+ "movq 14*8+0*8(%%"REG_S"), %%mm0 \n\t"
+ "pmullw %%mm7, %%mm6 \n\t"
+
+ "movq %%mm4, 7*8+4*8(%%"REG_D") \n\t"
+ "movq 14*8+1*8(%%"REG_S"), %%mm1 \n\t"
+ "pmullw %%mm7, %%mm0 \n\t"
+
+ "movq %%mm5, 7*8+5*8(%%"REG_D") \n\t"
+ "pmullw %%mm7, %%mm1 \n\t"
+
+ "movq %%mm6, 7*8+6*8(%%"REG_D") \n\t"
+ "movq %%mm0, 14*8+0*8(%%"REG_D") \n\t"
+ "movq %%mm1, 14*8+1*8(%%"REG_D") \n\t"
+
+ : "+g" (q), "+S" (adr), "+D" (adr)
+ :
+ );
+}
+
+static void column_fidct_mmx(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt);
+static void row_idct_mmx(DCTELEM* workspace,
+ int16_t* output_adr, int output_stride, int cnt);
+static void row_fdct_mmx(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt);
+
+#define store_slice_s store_slice_mmx
+#define store_slice2_s store_slice2_mmx
+#define mul_thrmat_s mul_thrmat_mmx
+#define column_fidct_s column_fidct_mmx
+#define row_idct_s row_idct_mmx
+#define row_fdct_s row_fdct_mmx
+#endif // HAVE_MMX
+
+static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src,
+ int dst_stride, int src_stride,
+ int width, int height,
+ uint8_t *qp_store, int qp_stride, int is_luma)
+{
+ int x, x0, y, es, qy, t;
+ const int stride= is_luma ? p->temp_stride : (width+16);//((width+16+15)&(~15))
+ const int step=6-p->log2_count;
+ const int qps= 3 + is_luma;
+ int32_t __attribute__((aligned(32))) block_align[4*8*BLOCKSZ+ 4*8*BLOCKSZ];
+ DCTELEM *block= (DCTELEM *)block_align;
+ DCTELEM *block3=(DCTELEM *)(block_align+4*8*BLOCKSZ);
+
+ memset(block3, 0, 4*8*BLOCKSZ);
+
+ //p->src=src-src_stride*8-8;//!
+ if (!src || !dst) return; // HACK avoid crash for Y8 colourspace
+ for(y=0; y<height; y++){
+ int index= 8 + 8*stride + y*stride;
+ fast_memcpy(p->src + index, src + y*src_stride, width);//this line can be avoided by using DR & user fr.buffers
+ for(x=0; x<8; x++){
+ p->src[index - x - 1]= p->src[index + x ];
+ p->src[index + width + x ]= p->src[index + width - x - 1];
+ }
+ }
+ for(y=0; y<8; y++){
+ fast_memcpy(p->src + ( 7-y)*stride, p->src + ( y+8)*stride, stride);
+ fast_memcpy(p->src + (height+8+y)*stride, p->src + (height-y+7)*stride, stride);
+ }
+ //FIXME (try edge emu)
+
+ for(y=8; y<24; y++)
+ memset(p->temp+ 8 +y*stride, 0,width*sizeof(int16_t));
+
+ for(y=step; y<height+8; y+=step){ //step= 1,2
+ qy=y-4;
+ if (qy>height-1) qy=height-1;
+ if (qy<0) qy=0;
+ qy=(qy>>qps)*qp_stride;
+ row_fdct_s(block, p->src + y*stride +2-(y&1), stride, 2);
+ for(x0=0; x0<width+8-8*(BLOCKSZ-1); x0+=8*(BLOCKSZ-1)){
+ row_fdct_s(block+8*8, p->src + y*stride+8+x0 +2-(y&1), stride, 2*(BLOCKSZ-1));
+ if(p->qp)
+ column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block+0*8, block3+0*8, 8*(BLOCKSZ-1)); //yes, this is a HOTSPOT
+ else
+ for (x=0; x<8*(BLOCKSZ-1); x+=8) {
+ t=x+x0-2; //correct t=x+x0-2-(y&1), but its the same
+ if (t<0) t=0;//t always < width-2
+ t=qp_store[qy+(t>>qps)];
+ t=norm_qscale(t, p->mpeg2);
+ if (t!=p->prev_q) p->prev_q=t, mul_thrmat_s(p, t);
+ column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block+x*8, block3+x*8, 8); //yes, this is a HOTSPOT
+ }
+ row_idct_s(block3+0*8, p->temp + (y&15)*stride+x0+2-(y&1), stride, 2*(BLOCKSZ-1));
+ memmove(block, block+(BLOCKSZ-1)*64, 8*8*sizeof(DCTELEM)); //cycling
+ memmove(block3, block3+(BLOCKSZ-1)*64, 6*8*sizeof(DCTELEM));
+ }
+ //
+ es=width+8-x0; // 8, ...
+ if (es>8)
+ row_fdct_s(block+8*8, p->src + y*stride+8+x0 +2-(y&1), stride, (es-4)>>2);
+ column_fidct_s((int16_t*)(&p->threshold_mtx[0]), block, block3, es&(~1));
+ row_idct_s(block3+0*8, p->temp + (y&15)*stride+x0+2-(y&1), stride, es>>2);
+ {const int y1=y-8+step;//l5-7 l4-6
+ if (!(y1&7) && y1) {
+ if (y1&8) store_slice_s(dst + (y1-8)*dst_stride, p->temp+ 8 +8*stride,
+ dst_stride, stride, width, 8, 5-p->log2_count);
+ else store_slice2_s(dst + (y1-8)*dst_stride, p->temp+ 8 +0*stride,
+ dst_stride, stride, width, 8, 5-p->log2_count);
+ } }
+ }
+
+ if (y&7) { // == height & 7
+ if (y&8) store_slice_s(dst + ((y-8)&~7)*dst_stride, p->temp+ 8 +8*stride,
+ dst_stride, stride, width, y&7, 5-p->log2_count);
+ else store_slice2_s(dst + ((y-8)&~7)*dst_stride, p->temp+ 8 +0*stride,
+ dst_stride, stride, width, y&7, 5-p->log2_count);
+ }
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ int h= (height+16+15)&(~15);
+
+ vf->priv->temp_stride= (width+16+15)&(~15);
+ vf->priv->temp= (int16_t*)av_mallocz(vf->priv->temp_stride*3*8*sizeof(int16_t));
+ //this can also be avoided, see above
+ vf->priv->src = (uint8_t*)av_malloc(vf->priv->temp_stride*h*sizeof(uint8_t));
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi)
+{
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags, mpi->width, mpi->height);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->width,mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+ }else{
+ dmpi=vf->dmpi;
+ }
+
+ vf->priv->mpeg2= mpi->qscale_type;
+ if(mpi->pict_type != 3 && mpi->qscale && !vf->priv->qp){
+ int w = mpi->qstride;
+ int h = (mpi->h + 15) >> 4;
+ if (!w) {
+ w = (mpi->w + 15) >> 4;
+ h = 1;
+ }
+ if(!vf->priv->non_b_qp)
+ vf->priv->non_b_qp= malloc(w*h);
+ fast_memcpy(vf->priv->non_b_qp, mpi->qscale, w*h);
+ }
+ if(vf->priv->log2_count || !(mpi->flags&MP_IMGFLAG_DIRECT)){
+ char *qp_tab= vf->priv->non_b_qp;
+ if(vf->priv->bframes || !qp_tab)
+ qp_tab= mpi->qscale;
+
+ if(qp_tab || vf->priv->qp){
+ filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0],
+ mpi->w, mpi->h, qp_tab, mpi->qstride, 1);
+ filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1],
+ mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
+ filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2],
+ mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
+ }else{
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
+ memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
+ }
+ }
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
+#endif
+#if HAVE_MMX2
+ if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
+#endif
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ if(!vf->priv) return;
+
+ av_free(vf->priv->temp);
+ vf->priv->temp= NULL;
+ av_free(vf->priv->src);
+ vf->priv->src= NULL;
+ //free(vf->priv->avctx);
+ //vf->priv->avctx= NULL;
+ free(vf->priv->non_b_qp);
+ vf->priv->non_b_qp= NULL;
+
+ av_free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ switch(fmt){
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+static int control(struct vf_instance *vf, int request, void* data)
+{
+ switch(request){
+ case VFCTRL_QUERY_MAX_PP_LEVEL:
+ return 5;
+ case VFCTRL_SET_PP_LEVEL:
+ vf->priv->log2_count= *((unsigned int*)data);
+ if (vf->priv->log2_count < 4) vf->priv->log2_count=4;
+ return CONTROL_TRUE;
+ }
+ return vf_next_control(vf,request,data);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ int i=0, bias;
+ int custom_threshold_m[64];
+ int log2c=-1;
+
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->control= control;
+ vf->priv=av_mallocz(sizeof(struct vf_priv_s));//assumes align 16 !
+
+ init_avcodec();
+
+ //vf->priv->avctx= avcodec_alloc_context();
+ //dsputil_init(&vf->priv->dsp, vf->priv->avctx);
+
+ vf->priv->log2_count= 4;
+ vf->priv->bframes = 0;
+
+ if (args) sscanf(args, "%d:%d:%d:%d", &log2c, &vf->priv->qp, &i, &vf->priv->bframes);
+
+ if( log2c >=4 && log2c <=5 )
+ vf->priv->log2_count = log2c;
+ else if( log2c >= 6 )
+ vf->priv->log2_count = 5;
+
+ if(vf->priv->qp < 0)
+ vf->priv->qp = 0;
+
+ if (i < -15) i = -15;
+ if (i > 32) i = 32;
+
+ bias= (1<<4)+i; //regulable
+ vf->priv->prev_q=0;
+ //
+ for(i=0;i<64;i++) //FIXME: tune custom_threshold[] and remove this !
+ custom_threshold_m[i]=(int)(custom_threshold[i]*(bias/71.)+ 0.5);
+ for(i=0;i<8;i++){
+ vf->priv->threshold_mtx_noq[2*i]=(uint64_t)custom_threshold_m[i*8+2]
+ |(((uint64_t)custom_threshold_m[i*8+6])<<16)
+ |(((uint64_t)custom_threshold_m[i*8+0])<<32)
+ |(((uint64_t)custom_threshold_m[i*8+4])<<48);
+ vf->priv->threshold_mtx_noq[2*i+1]=(uint64_t)custom_threshold_m[i*8+5]
+ |(((uint64_t)custom_threshold_m[i*8+3])<<16)
+ |(((uint64_t)custom_threshold_m[i*8+1])<<32)
+ |(((uint64_t)custom_threshold_m[i*8+7])<<48);
+ }
+
+ if (vf->priv->qp) vf->priv->prev_q=vf->priv->qp, mul_thrmat_s(vf->priv, vf->priv->qp);
+
+ return 1;
+}
+
+const vf_info_t vf_info_fspp = {
+ "fast simple postprocess",
+ "fspp",
+ "Michael Niedermayer, Nikolaj Poroshin",
+ "",
+ vf_open,
+ NULL
+};
+
+//====================================================================
+//Specific spp's dct, idct and threshold functions
+//I'd prefer to have them in the separate file.
+
+//#define MANGLE(a) #a
+
+//typedef int16_t DCTELEM; //! only int16_t
+
+#define DCTSIZE 8
+#define DCTSIZE_S "8"
+
+#define FIX(x,s) ((int) ((x) * (1<<s) + 0.5)&0xffff)
+#define C64(x) ((uint64_t)((x)|(x)<<16))<<32 | (uint64_t)(x) | (uint64_t)(x)<<16
+#define FIX64(x,s) C64(FIX(x,s))
+
+#define MULTIPLY16H(x,k) (((x)*(k))>>16)
+#define THRESHOLD(r,x,t) if(((unsigned)((x)+t))>t*2) r=(x);else r=0;
+#define DESCALE(x,n) (((x) + (1 << ((n)-1))) >> n)
+
+#if HAVE_MMX
+
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_382683433)=FIX64(0.382683433, 14);
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_541196100)=FIX64(0.541196100, 14);
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_707106781)=FIX64(0.707106781, 14);
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_306562965)=FIX64(1.306562965, 14);
+
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_414213562_A)=FIX64(1.414213562, 14);
+
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_847759065)=FIX64(1.847759065, 13);
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_2_613125930)=FIX64(-2.613125930, 13); //-
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_414213562)=FIX64(1.414213562, 13);
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_1_082392200)=FIX64(1.082392200, 13);
+//for t3,t5,t7 == 0 shortcut
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_847759065)=FIX64(0.847759065, 14);
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_566454497)=FIX64(0.566454497, 14);
+DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_198912367)=FIX64(0.198912367, 14);
+
+DECLARE_ASM_CONST(8, uint64_t, MM_DESCALE_RND)=C64(4);
+DECLARE_ASM_CONST(8, uint64_t, MM_2)=C64(2);
+
+#else /* !HAVE_MMX */
+
+typedef int32_t int_simd16_t;
+static const int16_t FIX_0_382683433=FIX(0.382683433, 14);
+static const int16_t FIX_0_541196100=FIX(0.541196100, 14);
+static const int16_t FIX_0_707106781=FIX(0.707106781, 14);
+static const int16_t FIX_1_306562965=FIX(1.306562965, 14);
+static const int16_t FIX_1_414213562_A=FIX(1.414213562, 14);
+static const int16_t FIX_1_847759065=FIX(1.847759065, 13);
+static const int16_t FIX_2_613125930=FIX(-2.613125930, 13); //-
+static const int16_t FIX_1_414213562=FIX(1.414213562, 13);
+static const int16_t FIX_1_082392200=FIX(1.082392200, 13);
+
+#endif
+
+#if !HAVE_MMX
+
+static void column_fidct_c(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt)
+{
+ int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_simd16_t tmp10, tmp11, tmp12, tmp13;
+ int_simd16_t z1,z2,z3,z4,z5, z10, z11, z12, z13;
+ int_simd16_t d0, d1, d2, d3, d4, d5, d6, d7;
+
+ DCTELEM* dataptr;
+ DCTELEM* wsptr;
+ int16_t *threshold;
+ int ctr;
+
+ dataptr = data;
+ wsptr = output;
+
+ for (; cnt > 0; cnt-=2) { //start positions
+ threshold=(int16_t*)thr_adr;//threshold_mtx
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ // Process columns from input, add to output.
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ // Even part of FDCT
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ d0 = tmp10 + tmp11;
+ d4 = tmp10 - tmp11;
+
+ z1 = MULTIPLY16H((tmp12 + tmp13) <<2, FIX_0_707106781);
+ d2 = tmp13 + z1;
+ d6 = tmp13 - z1;
+
+ // Even part of IDCT
+
+ THRESHOLD(tmp0, d0, threshold[0*8]);
+ THRESHOLD(tmp1, d2, threshold[2*8]);
+ THRESHOLD(tmp2, d4, threshold[4*8]);
+ THRESHOLD(tmp3, d6, threshold[6*8]);
+ tmp0+=2;
+ tmp10 = (tmp0 + tmp2)>>2;
+ tmp11 = (tmp0 - tmp2)>>2;
+
+ tmp13 = (tmp1 + tmp3)>>2; //+2 ! (psnr decides)
+ tmp12 = MULTIPLY16H((tmp1 - tmp3), FIX_1_414213562_A) - tmp13; //<<2
+
+ tmp0 = tmp10 + tmp13; //->temps
+ tmp3 = tmp10 - tmp13; //->temps
+ tmp1 = tmp11 + tmp12; //->temps
+ tmp2 = tmp11 - tmp12; //->temps
+
+ // Odd part of FDCT
+
+ tmp10 = tmp4 + tmp5;
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ z5 = MULTIPLY16H((tmp10 - tmp12)<<2, FIX_0_382683433);
+ z2 = MULTIPLY16H(tmp10 <<2, FIX_0_541196100) + z5;
+ z4 = MULTIPLY16H(tmp12 <<2, FIX_1_306562965) + z5;
+ z3 = MULTIPLY16H(tmp11 <<2, FIX_0_707106781);
+
+ z11 = tmp7 + z3;
+ z13 = tmp7 - z3;
+
+ d5 = z13 + z2;
+ d3 = z13 - z2;
+ d1 = z11 + z4;
+ d7 = z11 - z4;
+
+ // Odd part of IDCT
+
+ THRESHOLD(tmp4, d1, threshold[1*8]);
+ THRESHOLD(tmp5, d3, threshold[3*8]);
+ THRESHOLD(tmp6, d5, threshold[5*8]);
+ THRESHOLD(tmp7, d7, threshold[7*8]);
+
+ //Simd version uses here a shortcut for the tmp5,tmp6,tmp7 == 0
+ z13 = tmp6 + tmp5;
+ z10 = (tmp6 - tmp5)<<1;
+ z11 = tmp4 + tmp7;
+ z12 = (tmp4 - tmp7)<<1;
+
+ tmp7 = (z11 + z13)>>2; //+2 !
+ tmp11 = MULTIPLY16H((z11 - z13)<<1, FIX_1_414213562);
+ z5 = MULTIPLY16H(z10 + z12, FIX_1_847759065);
+ tmp10 = MULTIPLY16H(z12, FIX_1_082392200) - z5;
+ tmp12 = MULTIPLY16H(z10, FIX_2_613125930) + z5; // - !!
+
+ tmp6 = tmp12 - tmp7;
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ wsptr[DCTSIZE*0]+= (tmp0 + tmp7);
+ wsptr[DCTSIZE*1]+= (tmp1 + tmp6);
+ wsptr[DCTSIZE*2]+= (tmp2 + tmp5);
+ wsptr[DCTSIZE*3]+= (tmp3 - tmp4);
+ wsptr[DCTSIZE*4]+= (tmp3 + tmp4);
+ wsptr[DCTSIZE*5]+= (tmp2 - tmp5);
+ wsptr[DCTSIZE*6]= (tmp1 - tmp6);
+ wsptr[DCTSIZE*7]= (tmp0 - tmp7);
+ //
+ dataptr++; //next column
+ wsptr++;
+ threshold++;
+ }
+ dataptr+=8; //skip each second start pos
+ wsptr +=8;
+ }
+}
+
+#else /* HAVE_MMX */
+
+static void column_fidct_mmx(int16_t* thr_adr, DCTELEM *data, DCTELEM *output, int cnt)
+{
+ uint64_t __attribute__((aligned(8))) temps[4];
+ __asm__ volatile(
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm1 \n\t"
+ //
+ "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm7 \n\t"
+ "movq %%mm1, %%mm0 \n\t"
+
+ "paddw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm1 \n\t" //t0
+ "movq %%mm7, %%mm3 \n\t"
+
+ "paddw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm7 \n\t" //t3
+ "movq %%mm1, %%mm5 \n\t"
+
+ "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm6 \n\t"
+ "psubw %%mm7, %%mm1 \n\t" //t13
+
+ "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
+ "movq %%mm6, %%mm4 \n\t"
+
+ "paddw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm6 \n\t" //t1
+ "paddw %%mm7, %%mm5 \n\t" //t10
+
+ "paddw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t2
+ "movq %%mm6, %%mm7 \n\t"
+
+ "paddw %%mm2, %%mm6 \n\t" //t11
+ "psubw %%mm2, %%mm7 \n\t" //t12
+
+ "movq %%mm5, %%mm2 \n\t"
+ "paddw %%mm6, %%mm5 \n\t" //d0
+ // i0 t13 t12 i3 i1 d0 - d4
+ "psubw %%mm6, %%mm2 \n\t" //d4
+ "paddw %%mm1, %%mm7 \n\t"
+
+ "movq 4*16(%%"REG_d"), %%mm6 \n\t"
+ "psllw $2, %%mm7 \n\t"
+
+ "psubw 0*16(%%"REG_d"), %%mm5 \n\t"
+ "psubw %%mm6, %%mm2 \n\t"
+
+ "paddusw 0*16(%%"REG_d"), %%mm5 \n\t"
+ "paddusw %%mm6, %%mm2 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t"
+ //
+ "paddw 0*16(%%"REG_d"), %%mm5 \n\t"
+ "paddw %%mm6, %%mm2 \n\t"
+
+ "psubusw 0*16(%%"REG_d"), %%mm5 \n\t"
+ "psubusw %%mm6, %%mm2 \n\t"
+
+//This func is totally compute-bound, operates at huge speed. So, DC shortcut
+// at this place isn't worthwhile due to BTB miss penalty (checked on Pent. 3).
+//However, typical numbers: nondc - 29%%, dc - 46%%, zero - 25%%. All <> 0 case is very rare.
+ "paddw "MANGLE(MM_2)", %%mm5 \n\t"
+ "movq %%mm2, %%mm6 \n\t"
+
+ "paddw %%mm5, %%mm2 \n\t"
+ "psubw %%mm6, %%mm5 \n\t"
+
+ "movq %%mm1, %%mm6 \n\t"
+ "paddw %%mm7, %%mm1 \n\t" //d2
+
+ "psubw 2*16(%%"REG_d"), %%mm1 \n\t"
+ "psubw %%mm7, %%mm6 \n\t" //d6
+
+ "movq 6*16(%%"REG_d"), %%mm7 \n\t"
+ "psraw $2, %%mm5 \n\t"
+
+ "paddusw 2*16(%%"REG_d"), %%mm1 \n\t"
+ "psubw %%mm7, %%mm6 \n\t"
+ // t7 d2 /t11 t4 t6 - d6 /t10
+
+ "paddw 2*16(%%"REG_d"), %%mm1 \n\t"
+ "paddusw %%mm7, %%mm6 \n\t"
+
+ "psubusw 2*16(%%"REG_d"), %%mm1 \n\t"
+ "paddw %%mm7, %%mm6 \n\t"
+
+ "psubw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm3 \n\t"
+ "psubusw %%mm7, %%mm6 \n\t"
+
+ //movq [edi+"DCTSIZE_S"*2*2], mm1
+ //movq [edi+"DCTSIZE_S"*6*2], mm6
+ "movq %%mm1, %%mm7 \n\t"
+ "psraw $2, %%mm2 \n\t"
+
+ "psubw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm4 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+
+ "psubw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm0 \n\t"
+ "paddw %%mm7, %%mm6 \n\t" //'t13
+
+ "psraw $2, %%mm6 \n\t" //paddw mm6, MM_2 !! ---
+ "movq %%mm2, %%mm7 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm1 \n\t"
+ "paddw %%mm6, %%mm2 \n\t" //'t0
+
+ "movq %%mm2, 0*8+%3 \n\t" //!
+ "psubw %%mm6, %%mm7 \n\t" //'t3
+
+ "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
+ "psubw %%mm6, %%mm1 \n\t" //'t12
+
+ "psubw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t5
+ "movq %%mm5, %%mm6 \n\t"
+
+ "movq %%mm7, 3*8+%3 \n\t"
+ "paddw %%mm2, %%mm3 \n\t" //t10
+
+ "paddw %%mm4, %%mm2 \n\t" //t11
+ "paddw %%mm0, %%mm4 \n\t" //t12
+
+ "movq %%mm3, %%mm7 \n\t"
+ "psubw %%mm4, %%mm3 \n\t"
+
+ "psllw $2, %%mm3 \n\t"
+ "psllw $2, %%mm7 \n\t" //opt for P6
+
+ "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t"
+ "psllw $2, %%mm4 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_541196100)", %%mm7 \n\t"
+ "psllw $2, %%mm2 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_306562965)", %%mm4 \n\t"
+ "paddw %%mm1, %%mm5 \n\t" //'t1
+
+ "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm2 \n\t"
+ "psubw %%mm1, %%mm6 \n\t" //'t2
+ // t7 't12 't11 t4 t6 - 't13 't10 ---
+
+ "paddw %%mm3, %%mm7 \n\t" //z2
+
+ "movq %%mm5, 1*8+%3 \n\t"
+ "paddw %%mm3, %%mm4 \n\t" //z4
+
+ "movq 3*16(%%"REG_d"), %%mm3 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+
+ "movq %%mm6, 2*8+%3 \n\t"
+ "psubw %%mm2, %%mm1 \n\t" //z13
+
+//===
+ "paddw %%mm2, %%mm0 \n\t" //z11
+ "movq %%mm1, %%mm5 \n\t"
+
+ "movq 5*16(%%"REG_d"), %%mm2 \n\t"
+ "psubw %%mm7, %%mm1 \n\t" //d3
+
+ "paddw %%mm7, %%mm5 \n\t" //d5
+ "psubw %%mm3, %%mm1 \n\t"
+
+ "movq 1*16(%%"REG_d"), %%mm7 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+
+ "movq %%mm0, %%mm6 \n\t"
+ "paddw %%mm4, %%mm0 \n\t" //d1
+
+ "paddusw %%mm3, %%mm1 \n\t"
+ "psubw %%mm4, %%mm6 \n\t" //d7
+
+ // d1 d3 - - - d5 d7 -
+ "movq 7*16(%%"REG_d"), %%mm4 \n\t"
+ "psubw %%mm7, %%mm0 \n\t"
+
+ "psubw %%mm4, %%mm6 \n\t"
+ "paddusw %%mm2, %%mm5 \n\t"
+
+ "paddusw %%mm4, %%mm6 \n\t"
+ "paddw %%mm3, %%mm1 \n\t"
+
+ "paddw %%mm2, %%mm5 \n\t"
+ "paddw %%mm4, %%mm6 \n\t"
+
+ "psubusw %%mm3, %%mm1 \n\t"
+ "psubusw %%mm2, %%mm5 \n\t"
+
+ "psubusw %%mm4, %%mm6 \n\t"
+ "movq %%mm1, %%mm4 \n\t"
+
+ "por %%mm5, %%mm4 \n\t"
+ "paddusw %%mm7, %%mm0 \n\t"
+
+ "por %%mm6, %%mm4 \n\t"
+ "paddw %%mm7, %%mm0 \n\t"
+
+ "packssdw %%mm4, %%mm4 \n\t"
+ "psubusw %%mm7, %%mm0 \n\t"
+
+ "movd %%mm4, %%"REG_a" \n\t"
+ "or %%"REG_a", %%"REG_a" \n\t"
+ "jnz 2f \n\t"
+ //movq [edi+"DCTSIZE_S"*3*2], mm1
+ //movq [edi+"DCTSIZE_S"*5*2], mm5
+ //movq [edi+"DCTSIZE_S"*1*2], mm0
+ //movq [edi+"DCTSIZE_S"*7*2], mm6
+ // t4 t5 - - - t6 t7 -
+ //--- t4 (mm0) may be <>0; mm1, mm5, mm6 == 0
+//Typical numbers: nondc - 19%%, dc - 26%%, zero - 55%%. zero case alone isn't worthwhile
+ "movq 0*8+%3, %%mm4 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_847759065)", %%mm0 \n\t" //tmp6
+ "movq %%mm1, %%mm2 \n\t"
+
+ "movq "DCTSIZE_S"*0*2(%%"REG_D"), %%mm5 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_566454497)", %%mm1 \n\t" //tmp5
+ "paddw %%mm4, %%mm5 \n\t"
+
+ "movq 1*8+%3, %%mm6 \n\t"
+ //paddw mm3, MM_2
+ "psraw $2, %%mm3 \n\t" //tmp7
+
+ "pmulhw "MANGLE(MM_FIX_0_198912367)", %%mm2 \n\t" //-tmp4
+ "psubw %%mm3, %%mm4 \n\t"
+
+ "movq "DCTSIZE_S"*1*2(%%"REG_D"), %%mm7 \n\t"
+ "paddw %%mm3, %%mm5 \n\t"
+
+ "movq %%mm4, "DCTSIZE_S"*7*2(%%"REG_D") \n\t"
+ "paddw %%mm6, %%mm7 \n\t"
+
+ "movq 2*8+%3, %%mm3 \n\t"
+ "psubw %%mm0, %%mm6 \n\t"
+
+ "movq "DCTSIZE_S"*2*2(%%"REG_D"), %%mm4 \n\t"
+ "paddw %%mm0, %%mm7 \n\t"
+
+ "movq %%mm5, "DCTSIZE_S"*0*2(%%"REG_D") \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*6*2(%%"REG_D") \n\t"
+ "psubw %%mm1, %%mm3 \n\t"
+
+ "movq "DCTSIZE_S"*5*2(%%"REG_D"), %%mm5 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+
+ "movq "DCTSIZE_S"*3*2(%%"REG_D"), %%mm6 \n\t"
+ "paddw %%mm3, %%mm5 \n\t"
+
+ "movq 3*8+%3, %%mm0 \n\t"
+ "add $8, %%"REG_S" \n\t"
+
+ "movq %%mm7, "DCTSIZE_S"*1*2(%%"REG_D") \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+
+ "movq %%mm4, "DCTSIZE_S"*2*2(%%"REG_D") \n\t"
+ "psubw %%mm2, %%mm0 \n\t"
+
+ "movq "DCTSIZE_S"*4*2(%%"REG_D"), %%mm7 \n\t"
+ "paddw %%mm2, %%mm6 \n\t"
+
+ "movq %%mm5, "DCTSIZE_S"*5*2(%%"REG_D") \n\t"
+ "paddw %%mm0, %%mm7 \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*3*2(%%"REG_D") \n\t"
+
+ "movq %%mm7, "DCTSIZE_S"*4*2(%%"REG_D") \n\t"
+ "add $8, %%"REG_D" \n\t"
+ "jmp 4f \n\t"
+
+ "2: \n\t"
+ //--- non DC2
+ //psraw mm1, 2 w/o it -> offset. thr1, thr1, thr1 (actually thr1, thr1, thr1-1)
+ //psraw mm5, 2
+ //psraw mm0, 2
+ //psraw mm6, 2
+ "movq %%mm5, %%mm3 \n\t"
+ "psubw %%mm1, %%mm5 \n\t"
+
+ "psllw $1, %%mm5 \n\t" //'z10
+ "paddw %%mm1, %%mm3 \n\t" //'z13
+
+ "movq %%mm0, %%mm2 \n\t"
+ "psubw %%mm6, %%mm0 \n\t"
+
+ "movq %%mm5, %%mm1 \n\t"
+ "psllw $1, %%mm0 \n\t" //'z12
+
+ "pmulhw "MANGLE(MM_FIX_2_613125930)", %%mm1 \n\t" //-
+ "paddw %%mm0, %%mm5 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_847759065)", %%mm5 \n\t" //'z5
+ "paddw %%mm6, %%mm2 \n\t" //'z11
+
+ "pmulhw "MANGLE(MM_FIX_1_082392200)", %%mm0 \n\t"
+ "movq %%mm2, %%mm7 \n\t"
+
+ //---
+ "movq 0*8+%3, %%mm4 \n\t"
+ "psubw %%mm3, %%mm2 \n\t"
+
+ "psllw $1, %%mm2 \n\t"
+ "paddw %%mm3, %%mm7 \n\t" //'t7
+
+ "pmulhw "MANGLE(MM_FIX_1_414213562)", %%mm2 \n\t" //'t11
+ "movq %%mm4, %%mm6 \n\t"
+ //paddw mm7, MM_2
+ "psraw $2, %%mm7 \n\t"
+
+ "paddw "DCTSIZE_S"*0*2(%%"REG_D"), %%mm4 \n\t"
+ "psubw %%mm7, %%mm6 \n\t"
+
+ "movq 1*8+%3, %%mm3 \n\t"
+ "paddw %%mm7, %%mm4 \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*7*2(%%"REG_D") \n\t"
+ "paddw %%mm5, %%mm1 \n\t" //'t12
+
+ "movq %%mm4, "DCTSIZE_S"*0*2(%%"REG_D") \n\t"
+ "psubw %%mm7, %%mm1 \n\t" //'t6
+
+ "movq 2*8+%3, %%mm7 \n\t"
+ "psubw %%mm5, %%mm0 \n\t" //'t10
+
+ "movq 3*8+%3, %%mm6 \n\t"
+ "movq %%mm3, %%mm5 \n\t"
+
+ "paddw "DCTSIZE_S"*1*2(%%"REG_D"), %%mm3 \n\t"
+ "psubw %%mm1, %%mm5 \n\t"
+
+ "psubw %%mm1, %%mm2 \n\t" //'t5
+ "paddw %%mm1, %%mm3 \n\t"
+
+ "movq %%mm5, "DCTSIZE_S"*6*2(%%"REG_D") \n\t"
+ "movq %%mm7, %%mm4 \n\t"
+
+ "paddw "DCTSIZE_S"*2*2(%%"REG_D"), %%mm7 \n\t"
+ "psubw %%mm2, %%mm4 \n\t"
+
+ "paddw "DCTSIZE_S"*5*2(%%"REG_D"), %%mm4 \n\t"
+ "paddw %%mm2, %%mm7 \n\t"
+
+ "movq %%mm3, "DCTSIZE_S"*1*2(%%"REG_D") \n\t"
+ "paddw %%mm2, %%mm0 \n\t" //'t4
+
+ // 't4 't6 't5 - - - - 't7
+ "movq %%mm7, "DCTSIZE_S"*2*2(%%"REG_D") \n\t"
+ "movq %%mm6, %%mm1 \n\t"
+
+ "paddw "DCTSIZE_S"*4*2(%%"REG_D"), %%mm6 \n\t"
+ "psubw %%mm0, %%mm1 \n\t"
+
+ "paddw "DCTSIZE_S"*3*2(%%"REG_D"), %%mm1 \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+
+ "movq %%mm4, "DCTSIZE_S"*5*2(%%"REG_D") \n\t"
+ "add $8, %%"REG_S" \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*4*2(%%"REG_D") \n\t"
+
+ "movq %%mm1, "DCTSIZE_S"*3*2(%%"REG_D") \n\t"
+ "add $8, %%"REG_D" \n\t"
+
+ "4: \n\t"
+//=part 2 (the same)===========================================================
+ "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm1 \n\t"
+ //
+ "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm7 \n\t"
+ "movq %%mm1, %%mm0 \n\t"
+
+ "paddw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm1 \n\t" //t0
+ "movq %%mm7, %%mm3 \n\t"
+
+ "paddw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm7 \n\t" //t3
+ "movq %%mm1, %%mm5 \n\t"
+
+ "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm6 \n\t"
+ "psubw %%mm7, %%mm1 \n\t" //t13
+
+ "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
+ "movq %%mm6, %%mm4 \n\t"
+
+ "paddw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm6 \n\t" //t1
+ "paddw %%mm7, %%mm5 \n\t" //t10
+
+ "paddw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t2
+ "movq %%mm6, %%mm7 \n\t"
+
+ "paddw %%mm2, %%mm6 \n\t" //t11
+ "psubw %%mm2, %%mm7 \n\t" //t12
+
+ "movq %%mm5, %%mm2 \n\t"
+ "paddw %%mm6, %%mm5 \n\t" //d0
+ // i0 t13 t12 i3 i1 d0 - d4
+ "psubw %%mm6, %%mm2 \n\t" //d4
+ "paddw %%mm1, %%mm7 \n\t"
+
+ "movq 1*8+4*16(%%"REG_d"), %%mm6 \n\t"
+ "psllw $2, %%mm7 \n\t"
+
+ "psubw 1*8+0*16(%%"REG_d"), %%mm5 \n\t"
+ "psubw %%mm6, %%mm2 \n\t"
+
+ "paddusw 1*8+0*16(%%"REG_d"), %%mm5 \n\t"
+ "paddusw %%mm6, %%mm2 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t"
+ //
+ "paddw 1*8+0*16(%%"REG_d"), %%mm5 \n\t"
+ "paddw %%mm6, %%mm2 \n\t"
+
+ "psubusw 1*8+0*16(%%"REG_d"), %%mm5 \n\t"
+ "psubusw %%mm6, %%mm2 \n\t"
+
+//This func is totally compute-bound, operates at huge speed. So, DC shortcut
+// at this place isn't worthwhile due to BTB miss penalty (checked on Pent. 3).
+//However, typical numbers: nondc - 29%%, dc - 46%%, zero - 25%%. All <> 0 case is very rare.
+ "paddw "MANGLE(MM_2)", %%mm5 \n\t"
+ "movq %%mm2, %%mm6 \n\t"
+
+ "paddw %%mm5, %%mm2 \n\t"
+ "psubw %%mm6, %%mm5 \n\t"
+
+ "movq %%mm1, %%mm6 \n\t"
+ "paddw %%mm7, %%mm1 \n\t" //d2
+
+ "psubw 1*8+2*16(%%"REG_d"), %%mm1 \n\t"
+ "psubw %%mm7, %%mm6 \n\t" //d6
+
+ "movq 1*8+6*16(%%"REG_d"), %%mm7 \n\t"
+ "psraw $2, %%mm5 \n\t"
+
+ "paddusw 1*8+2*16(%%"REG_d"), %%mm1 \n\t"
+ "psubw %%mm7, %%mm6 \n\t"
+ // t7 d2 /t11 t4 t6 - d6 /t10
+
+ "paddw 1*8+2*16(%%"REG_d"), %%mm1 \n\t"
+ "paddusw %%mm7, %%mm6 \n\t"
+
+ "psubusw 1*8+2*16(%%"REG_d"), %%mm1 \n\t"
+ "paddw %%mm7, %%mm6 \n\t"
+
+ "psubw "DCTSIZE_S"*4*2(%%"REG_S"), %%mm3 \n\t"
+ "psubusw %%mm7, %%mm6 \n\t"
+
+ //movq [edi+"DCTSIZE_S"*2*2], mm1
+ //movq [edi+"DCTSIZE_S"*6*2], mm6
+ "movq %%mm1, %%mm7 \n\t"
+ "psraw $2, %%mm2 \n\t"
+
+ "psubw "DCTSIZE_S"*6*2(%%"REG_S"), %%mm4 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+
+ "psubw "DCTSIZE_S"*7*2(%%"REG_S"), %%mm0 \n\t"
+ "paddw %%mm7, %%mm6 \n\t" //'t13
+
+ "psraw $2, %%mm6 \n\t" //paddw mm6, MM_2 !! ---
+ "movq %%mm2, %%mm7 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm1 \n\t"
+ "paddw %%mm6, %%mm2 \n\t" //'t0
+
+ "movq %%mm2, 0*8+%3 \n\t" //!
+ "psubw %%mm6, %%mm7 \n\t" //'t3
+
+ "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
+ "psubw %%mm6, %%mm1 \n\t" //'t12
+
+ "psubw "DCTSIZE_S"*5*2(%%"REG_S"), %%mm2 \n\t" //t5
+ "movq %%mm5, %%mm6 \n\t"
+
+ "movq %%mm7, 3*8+%3 \n\t"
+ "paddw %%mm2, %%mm3 \n\t" //t10
+
+ "paddw %%mm4, %%mm2 \n\t" //t11
+ "paddw %%mm0, %%mm4 \n\t" //t12
+
+ "movq %%mm3, %%mm7 \n\t"
+ "psubw %%mm4, %%mm3 \n\t"
+
+ "psllw $2, %%mm3 \n\t"
+ "psllw $2, %%mm7 \n\t" //opt for P6
+
+ "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t"
+ "psllw $2, %%mm4 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_541196100)", %%mm7 \n\t"
+ "psllw $2, %%mm2 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_306562965)", %%mm4 \n\t"
+ "paddw %%mm1, %%mm5 \n\t" //'t1
+
+ "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm2 \n\t"
+ "psubw %%mm1, %%mm6 \n\t" //'t2
+ // t7 't12 't11 t4 t6 - 't13 't10 ---
+
+ "paddw %%mm3, %%mm7 \n\t" //z2
+
+ "movq %%mm5, 1*8+%3 \n\t"
+ "paddw %%mm3, %%mm4 \n\t" //z4
+
+ "movq 1*8+3*16(%%"REG_d"), %%mm3 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+
+ "movq %%mm6, 2*8+%3 \n\t"
+ "psubw %%mm2, %%mm1 \n\t" //z13
+
+//===
+ "paddw %%mm2, %%mm0 \n\t" //z11
+ "movq %%mm1, %%mm5 \n\t"
+
+ "movq 1*8+5*16(%%"REG_d"), %%mm2 \n\t"
+ "psubw %%mm7, %%mm1 \n\t" //d3
+
+ "paddw %%mm7, %%mm5 \n\t" //d5
+ "psubw %%mm3, %%mm1 \n\t"
+
+ "movq 1*8+1*16(%%"REG_d"), %%mm7 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+
+ "movq %%mm0, %%mm6 \n\t"
+ "paddw %%mm4, %%mm0 \n\t" //d1
+
+ "paddusw %%mm3, %%mm1 \n\t"
+ "psubw %%mm4, %%mm6 \n\t" //d7
+
+ // d1 d3 - - - d5 d7 -
+ "movq 1*8+7*16(%%"REG_d"), %%mm4 \n\t"
+ "psubw %%mm7, %%mm0 \n\t"
+
+ "psubw %%mm4, %%mm6 \n\t"
+ "paddusw %%mm2, %%mm5 \n\t"
+
+ "paddusw %%mm4, %%mm6 \n\t"
+ "paddw %%mm3, %%mm1 \n\t"
+
+ "paddw %%mm2, %%mm5 \n\t"
+ "paddw %%mm4, %%mm6 \n\t"
+
+ "psubusw %%mm3, %%mm1 \n\t"
+ "psubusw %%mm2, %%mm5 \n\t"
+
+ "psubusw %%mm4, %%mm6 \n\t"
+ "movq %%mm1, %%mm4 \n\t"
+
+ "por %%mm5, %%mm4 \n\t"
+ "paddusw %%mm7, %%mm0 \n\t"
+
+ "por %%mm6, %%mm4 \n\t"
+ "paddw %%mm7, %%mm0 \n\t"
+
+ "packssdw %%mm4, %%mm4 \n\t"
+ "psubusw %%mm7, %%mm0 \n\t"
+
+ "movd %%mm4, %%"REG_a" \n\t"
+ "or %%"REG_a", %%"REG_a" \n\t"
+ "jnz 3f \n\t"
+ //movq [edi+"DCTSIZE_S"*3*2], mm1
+ //movq [edi+"DCTSIZE_S"*5*2], mm5
+ //movq [edi+"DCTSIZE_S"*1*2], mm0
+ //movq [edi+"DCTSIZE_S"*7*2], mm6
+ // t4 t5 - - - t6 t7 -
+ //--- t4 (mm0) may be <>0; mm1, mm5, mm6 == 0
+//Typical numbers: nondc - 19%%, dc - 26%%, zero - 55%%. zero case alone isn't worthwhile
+ "movq 0*8+%3, %%mm4 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_847759065)", %%mm0 \n\t" //tmp6
+ "movq %%mm1, %%mm2 \n\t"
+
+ "movq "DCTSIZE_S"*0*2(%%"REG_D"), %%mm5 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_566454497)", %%mm1 \n\t" //tmp5
+ "paddw %%mm4, %%mm5 \n\t"
+
+ "movq 1*8+%3, %%mm6 \n\t"
+ //paddw mm3, MM_2
+ "psraw $2, %%mm3 \n\t" //tmp7
+
+ "pmulhw "MANGLE(MM_FIX_0_198912367)", %%mm2 \n\t" //-tmp4
+ "psubw %%mm3, %%mm4 \n\t"
+
+ "movq "DCTSIZE_S"*1*2(%%"REG_D"), %%mm7 \n\t"
+ "paddw %%mm3, %%mm5 \n\t"
+
+ "movq %%mm4, "DCTSIZE_S"*7*2(%%"REG_D") \n\t"
+ "paddw %%mm6, %%mm7 \n\t"
+
+ "movq 2*8+%3, %%mm3 \n\t"
+ "psubw %%mm0, %%mm6 \n\t"
+
+ "movq "DCTSIZE_S"*2*2(%%"REG_D"), %%mm4 \n\t"
+ "paddw %%mm0, %%mm7 \n\t"
+
+ "movq %%mm5, "DCTSIZE_S"*0*2(%%"REG_D") \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*6*2(%%"REG_D") \n\t"
+ "psubw %%mm1, %%mm3 \n\t"
+
+ "movq "DCTSIZE_S"*5*2(%%"REG_D"), %%mm5 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+
+ "movq "DCTSIZE_S"*3*2(%%"REG_D"), %%mm6 \n\t"
+ "paddw %%mm3, %%mm5 \n\t"
+
+ "movq 3*8+%3, %%mm0 \n\t"
+ "add $24, %%"REG_S" \n\t"
+
+ "movq %%mm7, "DCTSIZE_S"*1*2(%%"REG_D") \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+
+ "movq %%mm4, "DCTSIZE_S"*2*2(%%"REG_D") \n\t"
+ "psubw %%mm2, %%mm0 \n\t"
+
+ "movq "DCTSIZE_S"*4*2(%%"REG_D"), %%mm7 \n\t"
+ "paddw %%mm2, %%mm6 \n\t"
+
+ "movq %%mm5, "DCTSIZE_S"*5*2(%%"REG_D") \n\t"
+ "paddw %%mm0, %%mm7 \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*3*2(%%"REG_D") \n\t"
+
+ "movq %%mm7, "DCTSIZE_S"*4*2(%%"REG_D") \n\t"
+ "add $24, %%"REG_D" \n\t"
+ "sub $2, %%"REG_c" \n\t"
+ "jnz 1b \n\t"
+ "jmp 5f \n\t"
+
+ "3: \n\t"
+ //--- non DC2
+ //psraw mm1, 2 w/o it -> offset. thr1, thr1, thr1 (actually thr1, thr1, thr1-1)
+ //psraw mm5, 2
+ //psraw mm0, 2
+ //psraw mm6, 2
+ "movq %%mm5, %%mm3 \n\t"
+ "psubw %%mm1, %%mm5 \n\t"
+
+ "psllw $1, %%mm5 \n\t" //'z10
+ "paddw %%mm1, %%mm3 \n\t" //'z13
+
+ "movq %%mm0, %%mm2 \n\t"
+ "psubw %%mm6, %%mm0 \n\t"
+
+ "movq %%mm5, %%mm1 \n\t"
+ "psllw $1, %%mm0 \n\t" //'z12
+
+ "pmulhw "MANGLE(MM_FIX_2_613125930)", %%mm1 \n\t" //-
+ "paddw %%mm0, %%mm5 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_847759065)", %%mm5 \n\t" //'z5
+ "paddw %%mm6, %%mm2 \n\t" //'z11
+
+ "pmulhw "MANGLE(MM_FIX_1_082392200)", %%mm0 \n\t"
+ "movq %%mm2, %%mm7 \n\t"
+
+ //---
+ "movq 0*8+%3, %%mm4 \n\t"
+ "psubw %%mm3, %%mm2 \n\t"
+
+ "psllw $1, %%mm2 \n\t"
+ "paddw %%mm3, %%mm7 \n\t" //'t7
+
+ "pmulhw "MANGLE(MM_FIX_1_414213562)", %%mm2 \n\t" //'t11
+ "movq %%mm4, %%mm6 \n\t"
+ //paddw mm7, MM_2
+ "psraw $2, %%mm7 \n\t"
+
+ "paddw "DCTSIZE_S"*0*2(%%"REG_D"), %%mm4 \n\t"
+ "psubw %%mm7, %%mm6 \n\t"
+
+ "movq 1*8+%3, %%mm3 \n\t"
+ "paddw %%mm7, %%mm4 \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*7*2(%%"REG_D") \n\t"
+ "paddw %%mm5, %%mm1 \n\t" //'t12
+
+ "movq %%mm4, "DCTSIZE_S"*0*2(%%"REG_D") \n\t"
+ "psubw %%mm7, %%mm1 \n\t" //'t6
+
+ "movq 2*8+%3, %%mm7 \n\t"
+ "psubw %%mm5, %%mm0 \n\t" //'t10
+
+ "movq 3*8+%3, %%mm6 \n\t"
+ "movq %%mm3, %%mm5 \n\t"
+
+ "paddw "DCTSIZE_S"*1*2(%%"REG_D"), %%mm3 \n\t"
+ "psubw %%mm1, %%mm5 \n\t"
+
+ "psubw %%mm1, %%mm2 \n\t" //'t5
+ "paddw %%mm1, %%mm3 \n\t"
+
+ "movq %%mm5, "DCTSIZE_S"*6*2(%%"REG_D") \n\t"
+ "movq %%mm7, %%mm4 \n\t"
+
+ "paddw "DCTSIZE_S"*2*2(%%"REG_D"), %%mm7 \n\t"
+ "psubw %%mm2, %%mm4 \n\t"
+
+ "paddw "DCTSIZE_S"*5*2(%%"REG_D"), %%mm4 \n\t"
+ "paddw %%mm2, %%mm7 \n\t"
+
+ "movq %%mm3, "DCTSIZE_S"*1*2(%%"REG_D") \n\t"
+ "paddw %%mm2, %%mm0 \n\t" //'t4
+
+ // 't4 't6 't5 - - - - 't7
+ "movq %%mm7, "DCTSIZE_S"*2*2(%%"REG_D") \n\t"
+ "movq %%mm6, %%mm1 \n\t"
+
+ "paddw "DCTSIZE_S"*4*2(%%"REG_D"), %%mm6 \n\t"
+ "psubw %%mm0, %%mm1 \n\t"
+
+ "paddw "DCTSIZE_S"*3*2(%%"REG_D"), %%mm1 \n\t"
+ "paddw %%mm0, %%mm6 \n\t"
+
+ "movq %%mm4, "DCTSIZE_S"*5*2(%%"REG_D") \n\t"
+ "add $24, %%"REG_S" \n\t"
+
+ "movq %%mm6, "DCTSIZE_S"*4*2(%%"REG_D") \n\t"
+
+ "movq %%mm1, "DCTSIZE_S"*3*2(%%"REG_D") \n\t"
+ "add $24, %%"REG_D" \n\t"
+ "sub $2, %%"REG_c" \n\t"
+ "jnz 1b \n\t"
+ "5: \n\t"
+
+ : "+S"(data), "+D"(output), "+c"(cnt), "=o"(temps)
+ : "d"(thr_adr)
+ : "%"REG_a
+ );
+}
+
+#endif // HAVE_MMX
+
+#if !HAVE_MMX
+
+static void row_idct_c(DCTELEM* workspace,
+ int16_t* output_adr, int output_stride, int cnt)
+{
+ int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_simd16_t tmp10, tmp11, tmp12, tmp13;
+ int_simd16_t z5, z10, z11, z12, z13;
+ int16_t* outptr;
+ DCTELEM* wsptr;
+
+ cnt*=4;
+ wsptr = workspace;
+ outptr = output_adr;
+ for (; cnt > 0; cnt--) {
+ // Even part
+ //Simd version reads 4x4 block and transposes it
+ tmp10 = ( wsptr[2] + wsptr[3]);
+ tmp11 = ( wsptr[2] - wsptr[3]);
+
+ tmp13 = ( wsptr[0] + wsptr[1]);
+ tmp12 = (MULTIPLY16H( wsptr[0] - wsptr[1], FIX_1_414213562_A)<<2) - tmp13;//this shift order to avoid overflow
+
+ tmp0 = tmp10 + tmp13; //->temps
+ tmp3 = tmp10 - tmp13; //->temps
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ // Odd part
+ //Also transpose, with previous:
+ // ---- ---- ||||
+ // ---- ---- idct ||||
+ // ---- ---- ---> ||||
+ // ---- ---- ||||
+ z13 = wsptr[4] + wsptr[5];
+ z10 = wsptr[4] - wsptr[5];
+ z11 = wsptr[6] + wsptr[7];
+ z12 = wsptr[6] - wsptr[7];
+
+ tmp7 = z11 + z13;
+ tmp11 = MULTIPLY16H(z11 - z13, FIX_1_414213562);
+
+ z5 = MULTIPLY16H(z10 + z12, FIX_1_847759065);
+ tmp10 = MULTIPLY16H(z12, FIX_1_082392200) - z5;
+ tmp12 = MULTIPLY16H(z10, FIX_2_613125930) + z5; // - FIX_
+
+ tmp6 = (tmp12<<3) - tmp7;
+ tmp5 = (tmp11<<3) - tmp6;
+ tmp4 = (tmp10<<3) + tmp5;
+
+ // Final output stage: descale and write column
+ outptr[0*output_stride]+= DESCALE(tmp0 + tmp7, 3);
+ outptr[1*output_stride]+= DESCALE(tmp1 + tmp6, 3);
+ outptr[2*output_stride]+= DESCALE(tmp2 + tmp5, 3);
+ outptr[3*output_stride]+= DESCALE(tmp3 - tmp4, 3);
+ outptr[4*output_stride]+= DESCALE(tmp3 + tmp4, 3);
+ outptr[5*output_stride]+= DESCALE(tmp2 - tmp5, 3);
+ outptr[6*output_stride]+= DESCALE(tmp1 - tmp6, 3); //no += ?
+ outptr[7*output_stride]+= DESCALE(tmp0 - tmp7, 3); //no += ?
+ outptr++;
+
+ wsptr += DCTSIZE; // advance pointer to next row
+ }
+}
+
+#else /* HAVE_MMX */
+
+static void row_idct_mmx (DCTELEM* workspace,
+ int16_t* output_adr, int output_stride, int cnt)
+{
+ uint64_t __attribute__((aligned(8))) temps[4];
+ __asm__ volatile(
+ "lea (%%"REG_a",%%"REG_a",2), %%"REG_d" \n\t"
+ "1: \n\t"
+ "movq "DCTSIZE_S"*0*2(%%"REG_S"), %%mm0 \n\t"
+ //
+
+ "movq "DCTSIZE_S"*1*2(%%"REG_S"), %%mm1 \n\t"
+ "movq %%mm0, %%mm4 \n\t"
+
+ "movq "DCTSIZE_S"*2*2(%%"REG_S"), %%mm2 \n\t"
+ "punpcklwd %%mm1, %%mm0 \n\t"
+
+ "movq "DCTSIZE_S"*3*2(%%"REG_S"), %%mm3 \n\t"
+ "punpckhwd %%mm1, %%mm4 \n\t"
+
+ //transpose 4x4
+ "movq %%mm2, %%mm7 \n\t"
+ "punpcklwd %%mm3, %%mm2 \n\t"
+
+ "movq %%mm0, %%mm6 \n\t"
+ "punpckldq %%mm2, %%mm0 \n\t" //0
+
+ "punpckhdq %%mm2, %%mm6 \n\t" //1
+ "movq %%mm0, %%mm5 \n\t"
+
+ "punpckhwd %%mm3, %%mm7 \n\t"
+ "psubw %%mm6, %%mm0 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_414213562_A)", %%mm0 \n\t"
+ "movq %%mm4, %%mm2 \n\t"
+
+ "punpckldq %%mm7, %%mm4 \n\t" //2
+ "paddw %%mm6, %%mm5 \n\t"
+
+ "punpckhdq %%mm7, %%mm2 \n\t" //3
+ "movq %%mm4, %%mm1 \n\t"
+
+ "psllw $2, %%mm0 \n\t"
+ "paddw %%mm2, %%mm4 \n\t" //t10
+
+ "movq "DCTSIZE_S"*0*2+"DCTSIZE_S"(%%"REG_S"), %%mm3 \n\t"
+ "psubw %%mm2, %%mm1 \n\t" //t11
+
+ "movq "DCTSIZE_S"*1*2+"DCTSIZE_S"(%%"REG_S"), %%mm2 \n\t"
+ "psubw %%mm5, %%mm0 \n\t"
+
+ "movq %%mm4, %%mm6 \n\t"
+ "paddw %%mm5, %%mm4 \n\t" //t0
+
+ "psubw %%mm5, %%mm6 \n\t" //t3
+ "movq %%mm1, %%mm7 \n\t"
+
+ "movq "DCTSIZE_S"*2*2+"DCTSIZE_S"(%%"REG_S"), %%mm5 \n\t"
+ "paddw %%mm0, %%mm1 \n\t" //t1
+
+ "movq %%mm4, 0*8+%3 \n\t" //t0
+ "movq %%mm3, %%mm4 \n\t"
+
+ "movq %%mm6, 1*8+%3 \n\t" //t3
+ "punpcklwd %%mm2, %%mm3 \n\t"
+
+ //transpose 4x4
+ "movq "DCTSIZE_S"*3*2+"DCTSIZE_S"(%%"REG_S"), %%mm6 \n\t"
+ "punpckhwd %%mm2, %%mm4 \n\t"
+
+ "movq %%mm5, %%mm2 \n\t"
+ "punpcklwd %%mm6, %%mm5 \n\t"
+
+ "psubw %%mm0, %%mm7 \n\t" //t2
+ "punpckhwd %%mm6, %%mm2 \n\t"
+
+ "movq %%mm3, %%mm0 \n\t"
+ "punpckldq %%mm5, %%mm3 \n\t" //4
+
+ "punpckhdq %%mm5, %%mm0 \n\t" //5
+ "movq %%mm4, %%mm5 \n\t"
+
+ //
+ "movq %%mm3, %%mm6 \n\t"
+ "punpckldq %%mm2, %%mm4 \n\t" //6
+
+ "psubw %%mm0, %%mm3 \n\t" //z10
+ "punpckhdq %%mm2, %%mm5 \n\t" //7
+
+ "paddw %%mm0, %%mm6 \n\t" //z13
+ "movq %%mm4, %%mm2 \n\t"
+
+ "movq %%mm3, %%mm0 \n\t"
+ "psubw %%mm5, %%mm4 \n\t" //z12
+
+ "pmulhw "MANGLE(MM_FIX_2_613125930)", %%mm0 \n\t" //-
+ "paddw %%mm4, %%mm3 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_847759065)", %%mm3 \n\t" //z5
+ "paddw %%mm5, %%mm2 \n\t" //z11 >
+
+ "pmulhw "MANGLE(MM_FIX_1_082392200)", %%mm4 \n\t"
+ "movq %%mm2, %%mm5 \n\t"
+
+ "psubw %%mm6, %%mm2 \n\t"
+ "paddw %%mm6, %%mm5 \n\t" //t7
+
+ "pmulhw "MANGLE(MM_FIX_1_414213562)", %%mm2 \n\t" //t11
+ "paddw %%mm3, %%mm0 \n\t" //t12
+
+ "psllw $3, %%mm0 \n\t"
+ "psubw %%mm3, %%mm4 \n\t" //t10
+
+ "movq 0*8+%3, %%mm6 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+
+ "psllw $3, %%mm4 \n\t"
+ "psubw %%mm5, %%mm0 \n\t" //t6
+
+ "psllw $3, %%mm2 \n\t"
+ "paddw %%mm0, %%mm1 \n\t" //d1
+
+ "psubw %%mm0, %%mm2 \n\t" //t5
+ "psubw %%mm0, %%mm3 \n\t" //d6
+
+ "paddw %%mm2, %%mm4 \n\t" //t4
+ "movq %%mm7, %%mm0 \n\t"
+
+ "paddw %%mm2, %%mm7 \n\t" //d2
+ "psubw %%mm2, %%mm0 \n\t" //d5
+
+ "movq "MANGLE(MM_DESCALE_RND)", %%mm2 \n\t" //4
+ "psubw %%mm5, %%mm6 \n\t" //d7
+
+ "paddw 0*8+%3, %%mm5 \n\t" //d0
+ "paddw %%mm2, %%mm1 \n\t"
+
+ "paddw %%mm2, %%mm5 \n\t"
+ "psraw $3, %%mm1 \n\t"
+
+ "paddw %%mm2, %%mm7 \n\t"
+ "psraw $3, %%mm5 \n\t"
+
+ "paddw (%%"REG_D"), %%mm5 \n\t"
+ "psraw $3, %%mm7 \n\t"
+
+ "paddw (%%"REG_D",%%"REG_a",), %%mm1 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+
+ "paddw (%%"REG_D",%%"REG_a",2), %%mm7 \n\t"
+ "paddw %%mm2, %%mm3 \n\t"
+
+ "movq %%mm5, (%%"REG_D") \n\t"
+ "paddw %%mm2, %%mm6 \n\t"
+
+ "movq %%mm1, (%%"REG_D",%%"REG_a",) \n\t"
+ "psraw $3, %%mm0 \n\t"
+
+ "movq %%mm7, (%%"REG_D",%%"REG_a",2) \n\t"
+ "add %%"REG_d", %%"REG_D" \n\t" //3*ls
+
+ "movq 1*8+%3, %%mm5 \n\t" //t3
+ "psraw $3, %%mm3 \n\t"
+
+ "paddw (%%"REG_D",%%"REG_a",2), %%mm0 \n\t"
+ "psubw %%mm4, %%mm5 \n\t" //d3
+
+ "paddw (%%"REG_D",%%"REG_d",), %%mm3 \n\t"
+ "psraw $3, %%mm6 \n\t"
+
+ "paddw 1*8+%3, %%mm4 \n\t" //d4
+ "paddw %%mm2, %%mm5 \n\t"
+
+ "paddw (%%"REG_D",%%"REG_a",4), %%mm6 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+
+ "movq %%mm0, (%%"REG_D",%%"REG_a",2) \n\t"
+ "psraw $3, %%mm5 \n\t"
+
+ "paddw (%%"REG_D"), %%mm5 \n\t"
+ "psraw $3, %%mm4 \n\t"
+
+ "paddw (%%"REG_D",%%"REG_a",), %%mm4 \n\t"
+ "add $"DCTSIZE_S"*2*4, %%"REG_S" \n\t" //4 rows
+
+ "movq %%mm3, (%%"REG_D",%%"REG_d",) \n\t"
+ "movq %%mm6, (%%"REG_D",%%"REG_a",4) \n\t"
+ "movq %%mm5, (%%"REG_D") \n\t"
+ "movq %%mm4, (%%"REG_D",%%"REG_a",) \n\t"
+
+ "sub %%"REG_d", %%"REG_D" \n\t"
+ "add $8, %%"REG_D" \n\t"
+ "dec %%"REG_c" \n\t"
+ "jnz 1b \n\t"
+
+ : "+S"(workspace), "+D"(output_adr), "+c"(cnt), "=o"(temps)
+ : "a"(output_stride*sizeof(short))
+ : "%"REG_d
+ );
+}
+
+#endif // HAVE_MMX
+
+#if !HAVE_MMX
+
+static void row_fdct_c(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt)
+{
+ int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_simd16_t tmp10, tmp11, tmp12, tmp13;
+ int_simd16_t z1, z2, z3, z4, z5, z11, z13;
+ DCTELEM *dataptr;
+
+ cnt*=4;
+ // Pass 1: process rows.
+
+ dataptr = data;
+ for (; cnt > 0; cnt--) {
+ tmp0 = pixels[line_size*0] + pixels[line_size*7];
+ tmp7 = pixels[line_size*0] - pixels[line_size*7];
+ tmp1 = pixels[line_size*1] + pixels[line_size*6];
+ tmp6 = pixels[line_size*1] - pixels[line_size*6];
+ tmp2 = pixels[line_size*2] + pixels[line_size*5];
+ tmp5 = pixels[line_size*2] - pixels[line_size*5];
+ tmp3 = pixels[line_size*3] + pixels[line_size*4];
+ tmp4 = pixels[line_size*3] - pixels[line_size*4];
+
+ // Even part
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ //Even columns are written first, this leads to different order of columns
+ //in column_fidct(), but they are processed independently, so all ok.
+ //Later in the row_idct() columns readed at the same order.
+ dataptr[2] = tmp10 + tmp11;
+ dataptr[3] = tmp10 - tmp11;
+
+ z1 = MULTIPLY16H((tmp12 + tmp13)<<2, FIX_0_707106781);
+ dataptr[0] = tmp13 + z1;
+ dataptr[1] = tmp13 - z1;
+
+ // Odd part
+
+ tmp10 = (tmp4 + tmp5) <<2;
+ tmp11 = (tmp5 + tmp6) <<2;
+ tmp12 = (tmp6 + tmp7) <<2;
+
+ z5 = MULTIPLY16H(tmp10 - tmp12, FIX_0_382683433);
+ z2 = MULTIPLY16H(tmp10, FIX_0_541196100) + z5;
+ z4 = MULTIPLY16H(tmp12, FIX_1_306562965) + z5;
+ z3 = MULTIPLY16H(tmp11, FIX_0_707106781);
+
+ z11 = tmp7 + z3;
+ z13 = tmp7 - z3;
+
+ dataptr[4] = z13 + z2;
+ dataptr[5] = z13 - z2;
+ dataptr[6] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ pixels++; // advance pointer to next column
+ dataptr += DCTSIZE;
+ }
+}
+
+#else /* HAVE_MMX */
+
+static void row_fdct_mmx(DCTELEM *data, const uint8_t *pixels, int line_size, int cnt)
+{
+ uint64_t __attribute__((aligned(8))) temps[4];
+ __asm__ volatile(
+ "lea (%%"REG_a",%%"REG_a",2), %%"REG_d" \n\t"
+ "6: \n\t"
+ "movd (%%"REG_S"), %%mm0 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+
+ "movd (%%"REG_S",%%"REG_a",), %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+
+ "movd (%%"REG_S",%%"REG_a",2), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "add %%"REG_d", %%"REG_S" \n\t"
+
+ "movq %%mm0, %%mm5 \n\t"
+ //
+
+ "movd (%%"REG_S",%%"REG_a",4), %%mm3 \n\t" //7 ;prefetch!
+ "movq %%mm1, %%mm6 \n\t"
+
+ "movd (%%"REG_S",%%"REG_d",), %%mm4 \n\t" //6
+ "punpcklbw %%mm7, %%mm3 \n\t"
+
+ "psubw %%mm3, %%mm5 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+
+ "paddw %%mm3, %%mm0 \n\t"
+ "psubw %%mm4, %%mm6 \n\t"
+
+ "movd (%%"REG_S",%%"REG_a",2), %%mm3 \n\t" //5
+ "paddw %%mm4, %%mm1 \n\t"
+
+ "movq %%mm5, 0*8+%3 \n\t" //t7
+ "punpcklbw %%mm7, %%mm3 \n\t"
+
+ "movq %%mm6, 1*8+%3 \n\t" //t6
+ "movq %%mm2, %%mm4 \n\t"
+
+ "movd (%%"REG_S"), %%mm5 \n\t" //3
+ "paddw %%mm3, %%mm2 \n\t"
+
+ "movd (%%"REG_S",%%"REG_a",), %%mm6 \n\t" //4
+ "punpcklbw %%mm7, %%mm5 \n\t"
+
+ "psubw %%mm3, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm6 \n\t"
+
+ "movq %%mm5, %%mm3 \n\t"
+ "paddw %%mm6, %%mm5 \n\t" //t3
+
+ "psubw %%mm6, %%mm3 \n\t" //t4 ; t0 t1 t2 t4 t5 t3 - -
+ "movq %%mm0, %%mm6 \n\t"
+
+ "movq %%mm1, %%mm7 \n\t"
+ "psubw %%mm5, %%mm0 \n\t" //t13
+
+ "psubw %%mm2, %%mm1 \n\t"
+ "paddw %%mm2, %%mm7 \n\t" //t11
+
+ "paddw %%mm0, %%mm1 \n\t"
+ "movq %%mm7, %%mm2 \n\t"
+
+ "psllw $2, %%mm1 \n\t"
+ "paddw %%mm5, %%mm6 \n\t" //t10
+
+ "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm1 \n\t"
+ "paddw %%mm6, %%mm7 \n\t" //d2
+
+ "psubw %%mm2, %%mm6 \n\t" //d3
+ "movq %%mm0, %%mm5 \n\t"
+
+ //transpose 4x4
+ "movq %%mm7, %%mm2 \n\t"
+ "punpcklwd %%mm6, %%mm7 \n\t"
+
+ "paddw %%mm1, %%mm0 \n\t" //d0
+ "punpckhwd %%mm6, %%mm2 \n\t"
+
+ "psubw %%mm1, %%mm5 \n\t" //d1
+ "movq %%mm0, %%mm6 \n\t"
+
+ "movq 1*8+%3, %%mm1 \n\t"
+ "punpcklwd %%mm5, %%mm0 \n\t"
+
+ "punpckhwd %%mm5, %%mm6 \n\t"
+ "movq %%mm0, %%mm5 \n\t"
+
+ "punpckldq %%mm7, %%mm0 \n\t" //0
+ "paddw %%mm4, %%mm3 \n\t"
+
+ "punpckhdq %%mm7, %%mm5 \n\t" //1
+ "movq %%mm6, %%mm7 \n\t"
+
+ "movq %%mm0, "DCTSIZE_S"*0*2(%%"REG_D") \n\t"
+ "punpckldq %%mm2, %%mm6 \n\t" //2
+
+ "movq %%mm5, "DCTSIZE_S"*1*2(%%"REG_D") \n\t"
+ "punpckhdq %%mm2, %%mm7 \n\t" //3
+
+ "movq %%mm6, "DCTSIZE_S"*2*2(%%"REG_D") \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+
+ "movq %%mm7, "DCTSIZE_S"*3*2(%%"REG_D") \n\t"
+ "psllw $2, %%mm3 \n\t" //t10
+
+ "movq 0*8+%3, %%mm2 \n\t"
+ "psllw $2, %%mm4 \n\t" //t11
+
+ "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm4 \n\t" //z3
+ "paddw %%mm2, %%mm1 \n\t"
+
+ "psllw $2, %%mm1 \n\t" //t12
+ "movq %%mm3, %%mm0 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_541196100)", %%mm0 \n\t"
+ "psubw %%mm1, %%mm3 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_0_382683433)", %%mm3 \n\t" //z5
+ "movq %%mm2, %%mm5 \n\t"
+
+ "pmulhw "MANGLE(MM_FIX_1_306562965)", %%mm1 \n\t"
+ "psubw %%mm4, %%mm2 \n\t" //z13
+
+ "paddw %%mm4, %%mm5 \n\t" //z11
+ "movq %%mm2, %%mm6 \n\t"
+
+ "paddw %%mm3, %%mm0 \n\t" //z2
+ "movq %%mm5, %%mm7 \n\t"
+
+ "paddw %%mm0, %%mm2 \n\t" //d4
+ "psubw %%mm0, %%mm6 \n\t" //d5
+
+ "movq %%mm2, %%mm4 \n\t"
+ "paddw %%mm3, %%mm1 \n\t" //z4
+
+ //transpose 4x4
+ "punpcklwd %%mm6, %%mm2 \n\t"
+ "paddw %%mm1, %%mm5 \n\t" //d6
+
+ "punpckhwd %%mm6, %%mm4 \n\t"
+ "psubw %%mm1, %%mm7 \n\t" //d7
+
+ "movq %%mm5, %%mm6 \n\t"
+ "punpcklwd %%mm7, %%mm5 \n\t"
+
+ "punpckhwd %%mm7, %%mm6 \n\t"
+ "movq %%mm2, %%mm7 \n\t"
+
+ "punpckldq %%mm5, %%mm2 \n\t" //4
+ "sub %%"REG_d", %%"REG_S" \n\t"
+
+ "punpckhdq %%mm5, %%mm7 \n\t" //5
+ "movq %%mm4, %%mm5 \n\t"
+
+ "movq %%mm2, "DCTSIZE_S"*0*2+"DCTSIZE_S"(%%"REG_D") \n\t"
+ "punpckldq %%mm6, %%mm4 \n\t" //6
+
+ "movq %%mm7, "DCTSIZE_S"*1*2+"DCTSIZE_S"(%%"REG_D") \n\t"
+ "punpckhdq %%mm6, %%mm5 \n\t" //7
+
+ "movq %%mm4, "DCTSIZE_S"*2*2+"DCTSIZE_S"(%%"REG_D") \n\t"
+ "add $4, %%"REG_S" \n\t"
+
+ "movq %%mm5, "DCTSIZE_S"*3*2+"DCTSIZE_S"(%%"REG_D") \n\t"
+ "add $"DCTSIZE_S"*2*4, %%"REG_D" \n\t" //4 rows
+ "dec %%"REG_c" \n\t"
+ "jnz 6b \n\t"
+
+ : "+S"(pixels), "+D"(data), "+c"(cnt), "=o"(temps)
+ : "a"(line_size)
+ : "%"REG_d);
+}
+
+#endif // HAVE_MMX
diff --git a/libavfilter/libmpcodecs/vf_geq.c b/libavfilter/libmpcodecs/vf_geq.c
new file mode 100644
index 0000000000..ffbb42c331
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_geq.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libavcodec/avcodec.h"
+#include "libavutil/eval.h"
+
+struct vf_priv_s {
+ AVExpr * e[3];
+ int framenum;
+ mp_image_t *mpi;
+};
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static inline double getpix(struct vf_instance *vf, double x, double y, int plane){
+ int xi, yi;
+ mp_image_t *mpi= vf->priv->mpi;
+ int stride= mpi->stride[plane];
+ uint8_t *src= mpi->planes[plane];
+ xi=x= FFMIN(FFMAX(x, 0), (mpi->w >> (plane ? mpi->chroma_x_shift : 0))-1);
+ yi=y= FFMIN(FFMAX(y, 0), (mpi->h >> (plane ? mpi->chroma_y_shift : 0))-1);
+
+ x-=xi;
+ y-=yi;
+
+ return
+ (1-y)*((1-x)*src[xi + yi * stride] + x*src[xi + 1 + yi * stride])
+ + y *((1-x)*src[xi + (yi+1) * stride] + x*src[xi + 1 + (yi+1) * stride]);
+}
+
+//FIXME cubic interpolate
+//FIXME keep the last few frames
+static double lum(void *vf, double x, double y){
+ return getpix(vf, x, y, 0);
+}
+
+static double cb(void *vf, double x, double y){
+ return getpix(vf, x, y, 1);
+}
+
+static double cr(void *vf, double x, double y){
+ return getpix(vf, x, y, 2);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ int x,y, plane;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->w,mpi->h);
+ }
+
+ dmpi= vf->dmpi;
+ vf->priv->mpi= mpi;
+
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ for(plane=0; plane<3; plane++){
+ int w= mpi->w >> (plane ? mpi->chroma_x_shift : 0);
+ int h= mpi->h >> (plane ? mpi->chroma_y_shift : 0);
+ uint8_t *dst = dmpi->planes[plane];
+ int dst_stride= dmpi->stride[plane];
+ double const_values[]={
+ M_PI,
+ M_E,
+ 0,
+ 0,
+ w,
+ h,
+ vf->priv->framenum,
+ w/(double)mpi->w,
+ h/(double)mpi->h,
+ 0
+ };
+ if (!vf->priv->e[plane]) continue;
+ for(y=0; y<h; y++){
+ const_values[3]=y;
+ for(x=0; x<w; x++){
+ const_values[2]=x;
+ dst[x + y * dst_stride] = av_eval_expr(vf->priv->e[plane],
+ const_values, vf);
+ }
+ }
+ }
+
+ vf->priv->framenum++;
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ av_free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+static int vf_open(vf_instance_t *vf, char *args){
+ char eq[3][2000] = { { 0 }, { 0 }, { 0 } };
+ int plane, res;
+
+ vf->config=config;
+ vf->put_image=put_image;
+// vf->get_image=get_image;
+ vf->uninit=uninit;
+ vf->priv=av_malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if (args) sscanf(args, "%1999[^:]:%1999[^:]:%1999[^:]", eq[0], eq[1], eq[2]);
+
+ if (!eq[1][0]) strncpy(eq[1], eq[0], sizeof(eq[0])-1);
+ if (!eq[2][0]) strncpy(eq[2], eq[1], sizeof(eq[0])-1);
+
+ for(plane=0; plane<3; plane++){
+ static const char *const_names[]={
+ "PI",
+ "E",
+ "X",
+ "Y",
+ "W",
+ "H",
+ "N",
+ "SW",
+ "SH",
+ NULL
+ };
+ static const char *func2_names[]={
+ "lum",
+ "cb",
+ "cr",
+ "p",
+ NULL
+ };
+ double (*func2[])(void *, double, double)={
+ lum,
+ cb,
+ cr,
+ plane==0 ? lum : (plane==1 ? cb : cr),
+ NULL
+ };
+ res = av_parse_expr(&vf->priv->e[plane], eq[plane], const_names, NULL, NULL, func2_names, func2, 0, NULL);
+
+ if (res < 0) {
+ mp_msg(MSGT_VFILTER, MSGL_ERR, "geq: error loading equation `%s'\n", eq[plane]);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+const vf_info_t vf_info_geq = {
+ "generic equation filter",
+ "geq",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_gradfun.c b/libavfilter/libmpcodecs/vf_gradfun.c
new file mode 100644
index 0000000000..2732f55d9a
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_gradfun.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2009 Loren Merritt <lorenm@u.washignton.edu>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Debanding algorithm (from gradfun2db by prunedtree):
+ * Boxblur.
+ * Foreach pixel, if it's within threshold of the blurred value, make it closer.
+ * So now we have a smoothed and higher bitdepth version of all the shallow
+ * gradients, while leaving detailed areas untouched.
+ * Dither it back to 8bit.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "cpudetect.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+#include "libavutil/avutil.h"
+#include "libavutil/x86_cpu.h"
+
+struct vf_priv_s {
+ int thresh;
+ int radius;
+ uint16_t *buf;
+ void (*filter_line)(uint8_t *dst, uint8_t *src, uint16_t *dc,
+ int width, int thresh, const uint16_t *dithers);
+ void (*blur_line)(uint16_t *dc, uint16_t *buf, uint16_t *buf1,
+ uint8_t *src, int sstride, int width);
+};
+
+static const uint16_t __attribute__((aligned(16))) pw_7f[8] = {127,127,127,127,127,127,127,127};
+static const uint16_t __attribute__((aligned(16))) pw_ff[8] = {255,255,255,255,255,255,255,255};
+static const uint16_t __attribute__((aligned(16))) dither[8][8] = {
+ { 0, 96, 24,120, 6,102, 30,126 },
+ { 64, 32, 88, 56, 70, 38, 94, 62 },
+ { 16,112, 8,104, 22,118, 14,110 },
+ { 80, 48, 72, 40, 86, 54, 78, 46 },
+ { 4,100, 28,124, 2, 98, 26,122 },
+ { 68, 36, 92, 60, 66, 34, 90, 58 },
+ { 20,116, 12,108, 18,114, 10,106 },
+ { 84, 52, 76, 44, 82, 50, 74, 42 },
+};
+
+static void filter_line_c(uint8_t *dst, uint8_t *src, uint16_t *dc,
+ int width, int thresh, const uint16_t *dithers)
+{
+ int x;
+ for (x=0; x<width; x++, dc+=x&1) {
+ int pix = src[x]<<7;
+ int delta = dc[0] - pix;
+ int m = abs(delta) * thresh >> 16;
+ m = FFMAX(0, 127-m);
+ m = m*m*delta >> 14;
+ pix += m + dithers[x&7];
+ dst[x] = av_clip_uint8(pix>>7);
+ }
+}
+
+static void blur_line_c(uint16_t *dc, uint16_t *buf, uint16_t *buf1,
+ uint8_t *src, int sstride, int width)
+{
+ int x, v, old;
+ for (x=0; x<width; x++) {
+ v = buf1[x] + src[2*x] + src[2*x+1] + src[2*x+sstride] + src[2*x+1+sstride];
+ old = buf[x];
+ buf[x] = v;
+ dc[x] = v - old;
+ }
+}
+
+#if HAVE_MMX2
+static void filter_line_mmx2(uint8_t *dst, uint8_t *src, uint16_t *dc,
+ int width, int thresh, const uint16_t *dithers)
+{
+ intptr_t x;
+ if (width&3) {
+ x = width&~3;
+ filter_line_c(dst+x, src+x, dc+x/2, width-x, thresh, dithers);
+ width = x;
+ }
+ x = -width;
+ __asm__ volatile(
+ "movd %4, %%mm5 \n"
+ "pxor %%mm7, %%mm7 \n"
+ "pshufw $0, %%mm5, %%mm5 \n"
+ "movq %6, %%mm6 \n"
+ "movq %5, %%mm4 \n"
+ "1: \n"
+ "movd (%2,%0), %%mm0 \n"
+ "movd (%3,%0), %%mm1 \n"
+ "punpcklbw %%mm7, %%mm0 \n"
+ "punpcklwd %%mm1, %%mm1 \n"
+ "psllw $7, %%mm0 \n"
+ "pxor %%mm2, %%mm2 \n"
+ "psubw %%mm0, %%mm1 \n" // delta = dc - pix
+ "psubw %%mm1, %%mm2 \n"
+ "pmaxsw %%mm1, %%mm2 \n"
+ "pmulhuw %%mm5, %%mm2 \n" // m = abs(delta) * thresh >> 16
+ "psubw %%mm6, %%mm2 \n"
+ "pminsw %%mm7, %%mm2 \n" // m = -max(0, 127-m)
+ "pmullw %%mm2, %%mm2 \n"
+ "paddw %%mm4, %%mm0 \n" // pix += dither
+ "pmulhw %%mm2, %%mm1 \n"
+ "psllw $2, %%mm1 \n" // m = m*m*delta >> 14
+ "paddw %%mm1, %%mm0 \n" // pix += m
+ "psraw $7, %%mm0 \n"
+ "packuswb %%mm0, %%mm0 \n"
+ "movd %%mm0, (%1,%0) \n" // dst = clip(pix>>7)
+ "add $4, %0 \n"
+ "jl 1b \n"
+ "emms \n"
+ :"+r"(x)
+ :"r"(dst+width), "r"(src+width), "r"(dc+width/2),
+ "rm"(thresh), "m"(*dithers), "m"(*pw_7f)
+ :"memory"
+ );
+}
+#endif
+
+#if HAVE_SSSE3
+static void filter_line_ssse3(uint8_t *dst, uint8_t *src, uint16_t *dc,
+ int width, int thresh, const uint16_t *dithers)
+{
+ intptr_t x;
+ if (width&7) {
+ // could be 10% faster if I somehow eliminated this
+ x = width&~7;
+ filter_line_c(dst+x, src+x, dc+x/2, width-x, thresh, dithers);
+ width = x;
+ }
+ x = -width;
+ __asm__ volatile(
+ "movd %4, %%xmm5 \n"
+ "pxor %%xmm7, %%xmm7 \n"
+ "pshuflw $0,%%xmm5, %%xmm5 \n"
+ "movdqa %6, %%xmm6 \n"
+ "punpcklqdq %%xmm5, %%xmm5 \n"
+ "movdqa %5, %%xmm4 \n"
+ "1: \n"
+ "movq (%2,%0), %%xmm0 \n"
+ "movq (%3,%0), %%xmm1 \n"
+ "punpcklbw %%xmm7, %%xmm0 \n"
+ "punpcklwd %%xmm1, %%xmm1 \n"
+ "psllw $7, %%xmm0 \n"
+ "psubw %%xmm0, %%xmm1 \n" // delta = dc - pix
+ "pabsw %%xmm1, %%xmm2 \n"
+ "pmulhuw %%xmm5, %%xmm2 \n" // m = abs(delta) * thresh >> 16
+ "psubw %%xmm6, %%xmm2 \n"
+ "pminsw %%xmm7, %%xmm2 \n" // m = -max(0, 127-m)
+ "pmullw %%xmm2, %%xmm2 \n"
+ "psllw $1, %%xmm2 \n"
+ "paddw %%xmm4, %%xmm0 \n" // pix += dither
+ "pmulhrsw %%xmm2, %%xmm1 \n" // m = m*m*delta >> 14
+ "paddw %%xmm1, %%xmm0 \n" // pix += m
+ "psraw $7, %%xmm0 \n"
+ "packuswb %%xmm0, %%xmm0 \n"
+ "movq %%xmm0, (%1,%0) \n" // dst = clip(pix>>7)
+ "add $8, %0 \n"
+ "jl 1b \n"
+ :"+&r"(x)
+ :"r"(dst+width), "r"(src+width), "r"(dc+width/2),
+ "rm"(thresh), "m"(*dithers), "m"(*pw_7f)
+ :"memory"
+ );
+}
+#endif // HAVE_SSSE3
+
+#if HAVE_SSE2 && HAVE_6REGS
+#define BLURV(load)\
+ intptr_t x = -2*width;\
+ __asm__ volatile(\
+ "movdqa %6, %%xmm7 \n"\
+ "1: \n"\
+ load" (%4,%0), %%xmm0 \n"\
+ load" (%5,%0), %%xmm1 \n"\
+ "movdqa %%xmm0, %%xmm2 \n"\
+ "movdqa %%xmm1, %%xmm3 \n"\
+ "psrlw $8, %%xmm0 \n"\
+ "psrlw $8, %%xmm1 \n"\
+ "pand %%xmm7, %%xmm2 \n"\
+ "pand %%xmm7, %%xmm3 \n"\
+ "paddw %%xmm1, %%xmm0 \n"\
+ "paddw %%xmm3, %%xmm2 \n"\
+ "paddw %%xmm2, %%xmm0 \n"\
+ "paddw (%2,%0), %%xmm0 \n"\
+ "movdqa (%1,%0), %%xmm1 \n"\
+ "movdqa %%xmm0, (%1,%0) \n"\
+ "psubw %%xmm1, %%xmm0 \n"\
+ "movdqa %%xmm0, (%3,%0) \n"\
+ "add $16, %0 \n"\
+ "jl 1b \n"\
+ :"+&r"(x)\
+ :"r"(buf+width),\
+ "r"(buf1+width),\
+ "r"(dc+width),\
+ "r"(src+width*2),\
+ "r"(src+width*2+sstride),\
+ "m"(*pw_ff)\
+ :"memory"\
+ );
+
+static void blur_line_sse2(uint16_t *dc, uint16_t *buf, uint16_t *buf1,
+ uint8_t *src, int sstride, int width)
+{
+ if (((intptr_t)src|sstride)&15) {
+ BLURV("movdqu");
+ } else {
+ BLURV("movdqa");
+ }
+}
+#endif // HAVE_6REGS && HAVE_SSE2
+
+static void filter(struct vf_priv_s *ctx, uint8_t *dst, uint8_t *src,
+ int width, int height, int dstride, int sstride, int r)
+{
+ int bstride = ((width+15)&~15)/2;
+ int y;
+ uint32_t dc_factor = (1<<21)/(r*r);
+ uint16_t *dc = ctx->buf+16;
+ uint16_t *buf = ctx->buf+bstride+32;
+ int thresh = ctx->thresh;
+
+ memset(dc, 0, (bstride+16)*sizeof(*buf));
+ for (y=0; y<r; y++)
+ ctx->blur_line(dc, buf+y*bstride, buf+(y-1)*bstride, src+2*y*sstride, sstride, width/2);
+ for (;;) {
+ if (y < height-r) {
+ int mod = ((y+r)/2)%r;
+ uint16_t *buf0 = buf+mod*bstride;
+ uint16_t *buf1 = buf+(mod?mod-1:r-1)*bstride;
+ int x, v;
+ ctx->blur_line(dc, buf0, buf1, src+(y+r)*sstride, sstride, width/2);
+ for (x=v=0; x<r; x++)
+ v += dc[x];
+ for (; x<width/2; x++) {
+ v += dc[x] - dc[x-r];
+ dc[x-r] = v * dc_factor >> 16;
+ }
+ for (; x<(width+r+1)/2; x++)
+ dc[x-r] = v * dc_factor >> 16;
+ for (x=-r/2; x<0; x++)
+ dc[x] = dc[0];
+ }
+ if (y == r) {
+ for (y=0; y<r; y++)
+ ctx->filter_line(dst+y*dstride, src+y*sstride, dc-r/2, width, thresh, dither[y&7]);
+ }
+ ctx->filter_line(dst+y*dstride, src+y*sstride, dc-r/2, width, thresh, dither[y&7]);
+ if (++y >= height) break;
+ ctx->filter_line(dst+y*dstride, src+y*sstride, dc-r/2, width, thresh, dither[y&7]);
+ if (++y >= height) break;
+ }
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi)
+{
+ if (mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ // ok, we can do pp in-place:
+ vf->dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ mpi->type, mpi->flags, mpi->width, mpi->height);
+ mpi->planes[0] = vf->dmpi->planes[0];
+ mpi->stride[0] = vf->dmpi->stride[0];
+ mpi->width = vf->dmpi->width;
+ if (mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1] = vf->dmpi->planes[1];
+ mpi->planes[2] = vf->dmpi->planes[2];
+ mpi->stride[1] = vf->dmpi->stride[1];
+ mpi->stride[2] = vf->dmpi->stride[2];
+ }
+ mpi->flags |= MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi = vf->dmpi;
+ int p;
+
+ if (!(mpi->flags&MP_IMGFLAG_DIRECT)) {
+ // no DR, so get a new image. hope we'll get DR buffer:
+ dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->w, mpi->h);
+ }
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ for (p=0; p<mpi->num_planes; p++) {
+ int w = mpi->w;
+ int h = mpi->h;
+ int r = vf->priv->radius;
+ if (p) {
+ w >>= mpi->chroma_x_shift;
+ h >>= mpi->chroma_y_shift;
+ r = ((r>>mpi->chroma_x_shift) + (r>>mpi->chroma_y_shift)) / 2;
+ r = av_clip((r+1)&~1,4,32);
+ }
+ if (FFMIN(w,h) > 2*r)
+ filter(vf->priv, dmpi->planes[p], mpi->planes[p], w, h,
+ dmpi->stride[p], mpi->stride[p], r);
+ else if (dmpi->planes[p] != mpi->planes[p])
+ memcpy_pic(dmpi->planes[p], mpi->planes[p], w, h,
+ dmpi->stride[p], mpi->stride[p]);
+ }
+
+ return vf_next_put_image(vf, dmpi, pts);
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ switch (fmt){
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_NV12:
+ case IMGFMT_NV21:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ case IMGFMT_HM12:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ free(vf->priv->buf);
+ vf->priv->buf = av_mallocz((((width+15)&~15)*(vf->priv->radius+1)/2+32)*sizeof(uint16_t));
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ if (!vf->priv) return;
+ av_free(vf->priv->buf);
+ free(vf->priv);
+ vf->priv = NULL;
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ float thresh = 1.2;
+ int radius = 16;
+
+ vf->get_image=get_image;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->config=config;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if (args) sscanf(args, "%f:%d", &thresh, &radius);
+ vf->priv->thresh = (1<<15)/av_clipf(thresh,0.51,255);
+ vf->priv->radius = av_clip((radius+1)&~1,4,32);
+
+ vf->priv->blur_line = blur_line_c;
+ vf->priv->filter_line = filter_line_c;
+#if HAVE_SSE2 && HAVE_6REGS
+ if (gCpuCaps.hasSSE2)
+ vf->priv->blur_line = blur_line_sse2;
+#endif
+#if HAVE_MMX2
+ if (gCpuCaps.hasMMX2)
+ vf->priv->filter_line = filter_line_mmx2;
+#endif
+#if HAVE_SSSE3
+ if (gCpuCaps.hasSSSE3)
+ vf->priv->filter_line = filter_line_ssse3;
+#endif
+
+ return 1;
+}
+
+const vf_info_t vf_info_gradfun = {
+ "gradient deband",
+ "gradfun",
+ "Loren Merritt",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_harddup.c b/libavfilter/libmpcodecs/vf_harddup.c
new file mode 100644
index 0000000000..5b6c2ff010
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_harddup.c
@@ -0,0 +1,92 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ mp_image_t *last_mpi;
+};
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+
+ vf->priv->last_mpi = mpi;
+
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, 0, mpi->width, mpi->height);
+
+ dmpi->planes[0] = mpi->planes[0];
+ dmpi->stride[0] = mpi->stride[0];
+ if (dmpi->flags&MP_IMGFLAG_PLANAR) {
+ dmpi->planes[1] = mpi->planes[1];
+ dmpi->stride[1] = mpi->stride[1];
+ dmpi->planes[2] = mpi->planes[2];
+ dmpi->stride[2] = mpi->stride[2];
+ }
+
+ return vf_next_put_image(vf, dmpi, pts);
+}
+
+static int control(struct vf_instance *vf, int request, void* data)
+{
+ switch (request) {
+ case VFCTRL_DUPLICATE_FRAME:
+ if (!vf->priv->last_mpi) break;
+ // This is a huge hack. We assume nothing
+ // has been called earlier in the filter chain
+ // since the last put_image. This is reasonable
+ // because we're handling a duplicate frame!
+ if (put_image(vf, vf->priv->last_mpi, MP_NOPTS_VALUE))
+ return CONTROL_TRUE;
+ break;
+ }
+ return vf_next_control(vf, request, data);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->put_image = put_image;
+ vf->control = control;
+ vf->uninit = uninit;
+ vf->priv = calloc(1, sizeof(struct vf_priv_s));
+ return 1;
+}
+
+const vf_info_t vf_info_harddup = {
+ "resubmit duplicate frames for encoding",
+ "harddup",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_hqdn3d.c b/libavfilter/libmpcodecs/vf_hqdn3d.c
new file mode 100644
index 0000000000..eba3439d88
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_hqdn3d.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "mp_msg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#define PARAM1_DEFAULT 4.0
+#define PARAM2_DEFAULT 3.0
+#define PARAM3_DEFAULT 6.0
+
+//===========================================================================//
+
+struct vf_priv_s {
+ int Coefs[4][512*16];
+ unsigned int *Line;
+ unsigned short *Frame[3];
+};
+
+
+/***************************************************************************/
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv->Line);
+ free(vf->priv->Frame[0]);
+ free(vf->priv->Frame[1]);
+ free(vf->priv->Frame[2]);
+
+ vf->priv->Line = NULL;
+ vf->priv->Frame[0] = NULL;
+ vf->priv->Frame[1] = NULL;
+ vf->priv->Frame[2] = NULL;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ uninit(vf);
+ vf->priv->Line = malloc(width*sizeof(int));
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int* Coef){
+// int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
+ int dMul= PrevMul-CurrMul;
+ unsigned int d=((dMul+0x10007FF)>>12);
+ return CurrMul + Coef[d];
+}
+
+static void deNoiseTemporal(
+ unsigned char *Frame, // mpi->planes[x]
+ unsigned char *FrameDest, // dmpi->planes[x]
+ unsigned short *FrameAnt,
+ int W, int H, int sStride, int dStride,
+ int *Temporal)
+{
+ long X, Y;
+ unsigned int PixelDst;
+
+ for (Y = 0; Y < H; Y++){
+ for (X = 0; X < W; X++){
+ PixelDst = LowPassMul(FrameAnt[X]<<8, Frame[X]<<16, Temporal);
+ FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
+ FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
+ }
+ Frame += sStride;
+ FrameDest += dStride;
+ FrameAnt += W;
+ }
+}
+
+static void deNoiseSpacial(
+ unsigned char *Frame, // mpi->planes[x]
+ unsigned char *FrameDest, // dmpi->planes[x]
+ unsigned int *LineAnt, // vf->priv->Line (width bytes)
+ int W, int H, int sStride, int dStride,
+ int *Horizontal, int *Vertical)
+{
+ long X, Y;
+ long sLineOffs = 0, dLineOffs = 0;
+ unsigned int PixelAnt;
+ unsigned int PixelDst;
+
+ /* First pixel has no left nor top neighbor. */
+ PixelDst = LineAnt[0] = PixelAnt = Frame[0]<<16;
+ FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
+
+ /* First line has no top neighbor, only left. */
+ for (X = 1; X < W; X++){
+ PixelDst = LineAnt[X] = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
+ FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
+ }
+
+ for (Y = 1; Y < H; Y++){
+ unsigned int PixelAnt;
+ sLineOffs += sStride, dLineOffs += dStride;
+ /* First pixel on each line doesn't have previous pixel */
+ PixelAnt = Frame[sLineOffs]<<16;
+ PixelDst = LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
+ FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
+
+ for (X = 1; X < W; X++){
+ unsigned int PixelDst;
+ /* The rest are normal */
+ PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
+ PixelDst = LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
+ FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
+ }
+ }
+}
+
+static void deNoise(unsigned char *Frame, // mpi->planes[x]
+ unsigned char *FrameDest, // dmpi->planes[x]
+ unsigned int *LineAnt, // vf->priv->Line (width bytes)
+ unsigned short **FrameAntPtr,
+ int W, int H, int sStride, int dStride,
+ int *Horizontal, int *Vertical, int *Temporal)
+{
+ long X, Y;
+ long sLineOffs = 0, dLineOffs = 0;
+ unsigned int PixelAnt;
+ unsigned int PixelDst;
+ unsigned short* FrameAnt=(*FrameAntPtr);
+
+ if(!FrameAnt){
+ (*FrameAntPtr)=FrameAnt=malloc(W*H*sizeof(unsigned short));
+ for (Y = 0; Y < H; Y++){
+ unsigned short* dst=&FrameAnt[Y*W];
+ unsigned char* src=Frame+Y*sStride;
+ for (X = 0; X < W; X++) dst[X]=src[X]<<8;
+ }
+ }
+
+ if(!Horizontal[0] && !Vertical[0]){
+ deNoiseTemporal(Frame, FrameDest, FrameAnt,
+ W, H, sStride, dStride, Temporal);
+ return;
+ }
+ if(!Temporal[0]){
+ deNoiseSpacial(Frame, FrameDest, LineAnt,
+ W, H, sStride, dStride, Horizontal, Vertical);
+ return;
+ }
+
+ /* First pixel has no left nor top neighbor. Only previous frame */
+ LineAnt[0] = PixelAnt = Frame[0]<<16;
+ PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal);
+ FrameAnt[0] = ((PixelDst+0x1000007F)>>8);
+ FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
+
+ /* First line has no top neighbor. Only left one for each pixel and
+ * last frame */
+ for (X = 1; X < W; X++){
+ LineAnt[X] = PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
+ PixelDst = LowPassMul(FrameAnt[X]<<8, PixelAnt, Temporal);
+ FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
+ FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
+ }
+
+ for (Y = 1; Y < H; Y++){
+ unsigned int PixelAnt;
+ unsigned short* LinePrev=&FrameAnt[Y*W];
+ sLineOffs += sStride, dLineOffs += dStride;
+ /* First pixel on each line doesn't have previous pixel */
+ PixelAnt = Frame[sLineOffs]<<16;
+ LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
+ PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal);
+ LinePrev[0] = ((PixelDst+0x1000007F)>>8);
+ FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
+
+ for (X = 1; X < W; X++){
+ unsigned int PixelDst;
+ /* The rest are normal */
+ PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
+ LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
+ PixelDst = LowPassMul(LinePrev[X]<<8, LineAnt[X], Temporal);
+ LinePrev[X] = ((PixelDst+0x1000007F)>>8);
+ FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
+ }
+ }
+}
+
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+ int W = mpi->w, H = mpi->h;
+
+ mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+
+ if(!dmpi) return 0;
+
+ deNoise(mpi->planes[0], dmpi->planes[0],
+ vf->priv->Line, &vf->priv->Frame[0], W, H,
+ mpi->stride[0], dmpi->stride[0],
+ vf->priv->Coefs[0],
+ vf->priv->Coefs[0],
+ vf->priv->Coefs[1]);
+ deNoise(mpi->planes[1], dmpi->planes[1],
+ vf->priv->Line, &vf->priv->Frame[1], cw, ch,
+ mpi->stride[1], dmpi->stride[1],
+ vf->priv->Coefs[2],
+ vf->priv->Coefs[2],
+ vf->priv->Coefs[3]);
+ deNoise(mpi->planes[2], dmpi->planes[2],
+ vf->priv->Line, &vf->priv->Frame[2], cw, ch,
+ mpi->stride[2], dmpi->stride[2],
+ vf->priv->Coefs[2],
+ vf->priv->Coefs[2],
+ vf->priv->Coefs[3]);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+
+#define ABS(A) ( (A) > 0 ? (A) : -(A) )
+
+static void PrecalcCoefs(int *Ct, double Dist25)
+{
+ int i;
+ double Gamma, Simil, C;
+
+ Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001);
+
+ for (i = -255*16; i <= 255*16; i++)
+ {
+ Simil = 1.0 - ABS(i) / (16*255.0);
+ C = pow(Simil, Gamma) * 65536.0 * (double)i / 16.0;
+ Ct[16*256+i] = (C<0) ? (C-0.5) : (C+0.5);
+ }
+
+ Ct[0] = (Dist25 != 0);
+}
+
+
+static int vf_open(vf_instance_t *vf, char *args){
+ double LumSpac, LumTmp, ChromSpac, ChromTmp;
+ double Param1, Param2, Param3, Param4;
+
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if (args)
+ {
+ switch(sscanf(args, "%lf:%lf:%lf:%lf",
+ &Param1, &Param2, &Param3, &Param4
+ ))
+ {
+ case 0:
+ LumSpac = PARAM1_DEFAULT;
+ LumTmp = PARAM3_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ case 1:
+ LumSpac = Param1;
+ LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ case 2:
+ LumSpac = Param1;
+ LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
+
+ ChromSpac = Param2;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ case 3:
+ LumSpac = Param1;
+ LumTmp = Param3;
+
+ ChromSpac = Param2;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ break;
+
+ case 4:
+ LumSpac = Param1;
+ LumTmp = Param3;
+
+ ChromSpac = Param2;
+ ChromTmp = Param4;
+ break;
+
+ default:
+ LumSpac = PARAM1_DEFAULT;
+ LumTmp = PARAM3_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ }
+ }
+ else
+ {
+ LumSpac = PARAM1_DEFAULT;
+ LumTmp = PARAM3_DEFAULT;
+
+ ChromSpac = PARAM2_DEFAULT;
+ ChromTmp = LumTmp * ChromSpac / LumSpac;
+ }
+
+ PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
+ PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
+ PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
+ PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
+
+ return 1;
+}
+
+const vf_info_t vf_info_hqdn3d = {
+ "High Quality 3D Denoiser",
+ "hqdn3d",
+ "Daniel Moreno & A'rpi",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_hue.c b/libavfilter/libmpcodecs/vf_hue.c
new file mode 100644
index 0000000000..177142f032
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_hue.c
@@ -0,0 +1,200 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/video_out.h"
+
+#include "m_option.h"
+#include "m_struct.h"
+
+static struct vf_priv_s {
+ uint8_t *buf[2];
+ float hue;
+ float saturation;
+} const vf_priv_dflt = {
+ {NULL, NULL},
+ 0.0,
+ 1.0,
+};
+
+static void process_C(uint8_t *udst, uint8_t *vdst, uint8_t *usrc, uint8_t *vsrc, int dststride, int srcstride,
+ int w, int h, float hue, float sat)
+{
+ int i;
+ const int s= rint(sin(hue) * (1<<16) * sat);
+ const int c= rint(cos(hue) * (1<<16) * sat);
+
+ while (h--) {
+ for (i = 0; i<w; i++)
+ {
+ const int u= usrc[i] - 128;
+ const int v= vsrc[i] - 128;
+ int new_u= (c*u - s*v + (1<<15) + (128<<16))>>16;
+ int new_v= (s*u + c*v + (1<<15) + (128<<16))>>16;
+ if(new_u & 768) new_u= (-new_u)>>31;
+ if(new_v & 768) new_v= (-new_v)>>31;
+ udst[i]= new_u;
+ vdst[i]= new_v;
+ }
+ usrc += srcstride;
+ vsrc += srcstride;
+ udst += dststride;
+ vdst += dststride;
+ }
+}
+
+static void (*process)(uint8_t *udst, uint8_t *vdst, uint8_t *usrc, uint8_t *vsrc, int dststride, int srcstride,
+ int w, int h, float hue, float sat);
+
+/* FIXME: add packed yuv version of process */
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+
+ dmpi=vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, 0,
+ mpi->w, mpi->h);
+
+ dmpi->planes[0] = mpi->planes[0];
+ dmpi->stride[0] = mpi->stride[0];
+ dmpi->stride[1] = mpi->stride[1];
+ dmpi->stride[2] = mpi->stride[2];
+
+ if (!vf->priv->buf[0]){
+ vf->priv->buf[0] = malloc(mpi->stride[1]*mpi->h >> mpi->chroma_y_shift);
+ vf->priv->buf[1] = malloc(mpi->stride[2]*mpi->h >> mpi->chroma_y_shift);
+ }
+
+ if (vf->priv->hue == 0 && vf->priv->saturation == 1){
+ dmpi->planes[1] = mpi->planes[1];
+ dmpi->planes[2] = mpi->planes[2];
+ }else {
+ dmpi->planes[1] = vf->priv->buf[0];
+ dmpi->planes[2] = vf->priv->buf[1];
+ process(dmpi->planes[1], dmpi->planes[2],
+ mpi->planes[1], mpi->planes[2],
+ dmpi->stride[1],mpi->stride[1],
+ mpi->w>> mpi->chroma_x_shift, mpi->h>> mpi->chroma_y_shift,
+ vf->priv->hue, vf->priv->saturation);
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static int control(struct vf_instance *vf, int request, void* data)
+{
+ vf_equalizer_t *eq;
+
+ switch (request) {
+ case VFCTRL_SET_EQUALIZER:
+ eq = data;
+ if (!strcmp(eq->item,"hue")) {
+ vf->priv->hue = eq->value * M_PI / 100;
+ return CONTROL_TRUE;
+ } else if (!strcmp(eq->item,"saturation")) {
+ vf->priv->saturation = (eq->value + 100)/100.0;
+ return CONTROL_TRUE;
+ }
+ break;
+ case VFCTRL_GET_EQUALIZER:
+ eq = data;
+ if (!strcmp(eq->item,"hue")) {
+ eq->value = rint(vf->priv->hue *100 / M_PI);
+ return CONTROL_TRUE;
+ }else if (!strcmp(eq->item,"saturation")) {
+ eq->value = rint(vf->priv->saturation*100 - 100);
+ return CONTROL_TRUE;
+ }
+ break;
+ }
+ return vf_next_control(vf, request, data);
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ switch (fmt) {
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv->buf[0]);
+ free(vf->priv->buf[1]);
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->control=control;
+ vf->query_format=query_format;
+ vf->put_image=put_image;
+ vf->uninit=uninit;
+
+ vf->priv->hue *= M_PI / 180.0;
+
+ process = process_C;
+ return 1;
+}
+
+#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
+static const m_option_t vf_opts_fields[] = {
+ {"hue", ST_OFF(hue), CONF_TYPE_FLOAT, M_OPT_RANGE,-180.0 ,180.0, NULL},
+ {"saturation", ST_OFF(saturation), CONF_TYPE_FLOAT, M_OPT_RANGE,-10.0 ,10.0, NULL},
+ { NULL, NULL, 0, 0, 0, 0, NULL }
+};
+
+static const m_struct_t vf_opts = {
+ "hue",
+ sizeof(struct vf_priv_s),
+ &vf_priv_dflt,
+ vf_opts_fields
+};
+
+const vf_info_t vf_info_hue = {
+ "hue changer",
+ "hue",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ &vf_opts
+};
diff --git a/libavfilter/libmpcodecs/vf_il.c b/libavfilter/libmpcodecs/vf_il.c
new file mode 100644
index 0000000000..210e30d3f6
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_il.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "mp_msg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+
+
+//===========================================================================//
+
+typedef struct FilterParam{
+ int interleave;
+ int swap;
+}FilterParam;
+
+struct vf_priv_s {
+ FilterParam lumaParam;
+ FilterParam chromaParam;
+};
+
+/***************************************************************************/
+
+static void interleave(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int interleave, int swap){
+ const int a= swap;
+ const int b= 1-a;
+ const int m= h>>1;
+ int y;
+
+ switch(interleave){
+ case -1:
+ for(y=0; y < m; y++){
+ fast_memcpy(dst + dstStride* y , src + srcStride*(y*2 + a), w);
+ fast_memcpy(dst + dstStride*(y + m), src + srcStride*(y*2 + b), w);
+ }
+ break;
+ case 0:
+ for(y=0; y < m; y++){
+ fast_memcpy(dst + dstStride* y*2 , src + srcStride*(y*2 + a), w);
+ fast_memcpy(dst + dstStride*(y*2+1), src + srcStride*(y*2 + b), w);
+ }
+ break;
+ case 1:
+ for(y=0; y < m; y++){
+ fast_memcpy(dst + dstStride*(y*2+a), src + srcStride* y , w);
+ fast_memcpy(dst + dstStride*(y*2+b), src + srcStride*(y + m), w);
+ }
+ break;
+ }
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int w;
+ FilterParam *luma = &vf->priv->lumaParam;
+ FilterParam *chroma= &vf->priv->chromaParam;
+
+ mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+
+ if(mpi->flags&MP_IMGFLAG_PLANAR)
+ w= mpi->w;
+ else
+ w= mpi->w * mpi->bpp/8;
+
+ interleave(dmpi->planes[0], mpi->planes[0],
+ w, mpi->h, dmpi->stride[0], mpi->stride[0], luma->interleave, luma->swap);
+
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+
+ interleave(dmpi->planes[1], mpi->planes[1], cw,ch,
+ dmpi->stride[1], mpi->stride[1], chroma->interleave, luma->swap);
+ interleave(dmpi->planes[2], mpi->planes[2], cw,ch,
+ dmpi->stride[2], mpi->stride[2], chroma->interleave, luma->swap);
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static void parse(FilterParam *fp, char* args){
+ char *pos;
+ char *max= strchr(args, ':');
+
+ if(!max) max= args + strlen(args);
+
+ pos= strchr(args, 's');
+ if(pos && pos<max) fp->swap=1;
+ pos= strchr(args, 'i');
+ if(pos && pos<max) fp->interleave=1;
+ pos= strchr(args, 'd');
+ if(pos && pos<max) fp->interleave=-1;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+
+ vf->put_image=put_image;
+// vf->get_image=get_image;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if(args)
+ {
+ char *arg2= strchr(args,':');
+ if(arg2) parse(&vf->priv->chromaParam, arg2+1);
+ parse(&vf->priv->lumaParam, args);
+ }
+
+ return 1;
+}
+
+const vf_info_t vf_info_il = {
+ "(de)interleave",
+ "il",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_ilpack.c b/libavfilter/libmpcodecs/vf_ilpack.c
new file mode 100644
index 0000000000..77555a7b41
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_ilpack.c
@@ -0,0 +1,453 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+typedef void (pack_func_t)(unsigned char *dst, unsigned char *y,
+ unsigned char *u, unsigned char *v, int w, int us, int vs);
+
+struct vf_priv_s {
+ int mode;
+ pack_func_t *pack[2];
+};
+
+static void pack_nn_C(unsigned char *dst, unsigned char *y,
+ unsigned char *u, unsigned char *v, int w)
+{
+ int j;
+ for (j = w/2; j; j--) {
+ *dst++ = *y++;
+ *dst++ = *u++;
+ *dst++ = *y++;
+ *dst++ = *v++;
+ }
+}
+
+static void pack_li_0_C(unsigned char *dst, unsigned char *y,
+ unsigned char *u, unsigned char *v, int w, int us, int vs)
+{
+ int j;
+ for (j = w/2; j; j--) {
+ *dst++ = *y++;
+ *dst++ = (u[us+us] + 7*u[0])>>3;
+ *dst++ = *y++;
+ *dst++ = (v[vs+vs] + 7*v[0])>>3;
+ u++; v++;
+ }
+}
+
+static void pack_li_1_C(unsigned char *dst, unsigned char *y,
+ unsigned char *u, unsigned char *v, int w, int us, int vs)
+{
+ int j;
+ for (j = w/2; j; j--) {
+ *dst++ = *y++;
+ *dst++ = (3*u[us+us] + 5*u[0])>>3;
+ *dst++ = *y++;
+ *dst++ = (3*v[vs+vs] + 5*v[0])>>3;
+ u++; v++;
+ }
+}
+
+#if HAVE_MMX
+static void pack_nn_MMX(unsigned char *dst, unsigned char *y,
+ unsigned char *u, unsigned char *v, int w)
+{
+ __asm__ volatile (""
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%0), %%mm1 \n\t"
+ "movq (%0), %%mm2 \n\t"
+ "movq (%1), %%mm4 \n\t"
+ "movq (%2), %%mm6 \n\t"
+ "punpcklbw %%mm6, %%mm4 \n\t"
+ "punpcklbw %%mm4, %%mm1 \n\t"
+ "punpckhbw %%mm4, %%mm2 \n\t"
+
+ "add $8, %0 \n\t"
+ "add $4, %1 \n\t"
+ "add $4, %2 \n\t"
+ "movq %%mm1, (%3) \n\t"
+ "movq %%mm2, 8(%3) \n\t"
+ "add $16, %3 \n\t"
+ "decl %4 \n\t"
+ "jnz 1b \n\t"
+ "emms \n\t"
+ :
+ : "r" (y), "r" (u), "r" (v), "r" (dst), "r" (w/8)
+ : "memory"
+ );
+ pack_nn_C(dst, y, u, v, (w&7));
+}
+
+#if HAVE_EBX_AVAILABLE
+static void pack_li_0_MMX(unsigned char *dst, unsigned char *y,
+ unsigned char *u, unsigned char *v, int w, int us, int vs)
+{
+ __asm__ volatile (""
+ "push %%"REG_BP" \n\t"
+#if ARCH_X86_64
+ "mov %6, %%"REG_BP" \n\t"
+#else
+ "movl 4(%%"REG_d"), %%"REG_BP" \n\t"
+ "movl (%%"REG_d"), %%"REG_d" \n\t"
+#endif
+ "pxor %%mm0, %%mm0 \n\t"
+
+ ASMALIGN(4)
+ ".Lli0: \n\t"
+ "movq (%%"REG_S"), %%mm1 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+
+ "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
+ "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
+ "punpcklbw %%mm0, %%mm4 \n\t"
+ "punpcklbw %%mm0, %%mm6 \n\t"
+ "movq (%%"REG_a"), %%mm3 \n\t"
+ "movq (%%"REG_b"), %%mm5 \n\t"
+ "punpcklbw %%mm0, %%mm3 \n\t"
+ "punpcklbw %%mm0, %%mm5 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "psrlw $3, %%mm4 \n\t"
+ "psrlw $3, %%mm6 \n\t"
+ "packuswb %%mm4, %%mm4 \n\t"
+ "packuswb %%mm6, %%mm6 \n\t"
+ "punpcklbw %%mm6, %%mm4 \n\t"
+ "punpcklbw %%mm4, %%mm1 \n\t"
+ "punpckhbw %%mm4, %%mm2 \n\t"
+
+ "movq %%mm1, (%%"REG_D") \n\t"
+ "movq %%mm2, 8(%%"REG_D") \n\t"
+
+ "movq 8(%%"REG_S"), %%mm1 \n\t"
+ "movq 8(%%"REG_S"), %%mm2 \n\t"
+
+ "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
+ "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
+ "punpckhbw %%mm0, %%mm4 \n\t"
+ "punpckhbw %%mm0, %%mm6 \n\t"
+ "movq (%%"REG_a"), %%mm3 \n\t"
+ "movq (%%"REG_b"), %%mm5 \n\t"
+ "punpckhbw %%mm0, %%mm3 \n\t"
+ "punpckhbw %%mm0, %%mm5 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "psrlw $3, %%mm4 \n\t"
+ "psrlw $3, %%mm6 \n\t"
+ "packuswb %%mm4, %%mm4 \n\t"
+ "packuswb %%mm6, %%mm6 \n\t"
+ "punpcklbw %%mm6, %%mm4 \n\t"
+ "punpcklbw %%mm4, %%mm1 \n\t"
+ "punpckhbw %%mm4, %%mm2 \n\t"
+
+ "add $16, %%"REG_S" \n\t"
+ "add $8, %%"REG_a" \n\t"
+ "add $8, %%"REG_b" \n\t"
+
+ "movq %%mm1, 16(%%"REG_D") \n\t"
+ "movq %%mm2, 24(%%"REG_D") \n\t"
+ "add $32, %%"REG_D" \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz .Lli0 \n\t"
+ "emms \n\t"
+ "pop %%"REG_BP" \n\t"
+ :
+ : "S" (y), "D" (dst), "a" (u), "b" (v), "c" (w/16),
+#if ARCH_X86_64
+ "d" ((x86_reg)us), "r" ((x86_reg)vs)
+#else
+ "d" (&us)
+#endif
+ : "memory"
+ );
+ pack_li_0_C(dst, y, u, v, (w&15), us, vs);
+}
+
+static void pack_li_1_MMX(unsigned char *dst, unsigned char *y,
+ unsigned char *u, unsigned char *v, int w, int us, int vs)
+{
+ __asm__ volatile (""
+ "push %%"REG_BP" \n\t"
+#if ARCH_X86_64
+ "mov %6, %%"REG_BP" \n\t"
+#else
+ "movl 4(%%"REG_d"), %%"REG_BP" \n\t"
+ "movl (%%"REG_d"), %%"REG_d" \n\t"
+#endif
+ "pxor %%mm0, %%mm0 \n\t"
+
+ ASMALIGN(4)
+ ".Lli1: \n\t"
+ "movq (%%"REG_S"), %%mm1 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+
+ "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
+ "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
+ "punpcklbw %%mm0, %%mm4 \n\t"
+ "punpcklbw %%mm0, %%mm6 \n\t"
+ "movq (%%"REG_a"), %%mm3 \n\t"
+ "movq (%%"REG_b"), %%mm5 \n\t"
+ "punpcklbw %%mm0, %%mm3 \n\t"
+ "punpcklbw %%mm0, %%mm5 \n\t"
+ "movq %%mm4, %%mm7 \n\t"
+ "paddw %%mm4, %%mm4 \n\t"
+ "paddw %%mm7, %%mm4 \n\t"
+ "movq %%mm6, %%mm7 \n\t"
+ "paddw %%mm6, %%mm6 \n\t"
+ "paddw %%mm7, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "psrlw $3, %%mm4 \n\t"
+ "psrlw $3, %%mm6 \n\t"
+ "packuswb %%mm4, %%mm4 \n\t"
+ "packuswb %%mm6, %%mm6 \n\t"
+ "punpcklbw %%mm6, %%mm4 \n\t"
+ "punpcklbw %%mm4, %%mm1 \n\t"
+ "punpckhbw %%mm4, %%mm2 \n\t"
+
+ "movq %%mm1, (%%"REG_D") \n\t"
+ "movq %%mm2, 8(%%"REG_D") \n\t"
+
+ "movq 8(%%"REG_S"), %%mm1 \n\t"
+ "movq 8(%%"REG_S"), %%mm2 \n\t"
+
+ "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
+ "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
+ "punpckhbw %%mm0, %%mm4 \n\t"
+ "punpckhbw %%mm0, %%mm6 \n\t"
+ "movq (%%"REG_a"), %%mm3 \n\t"
+ "movq (%%"REG_b"), %%mm5 \n\t"
+ "punpckhbw %%mm0, %%mm3 \n\t"
+ "punpckhbw %%mm0, %%mm5 \n\t"
+ "movq %%mm4, %%mm7 \n\t"
+ "paddw %%mm4, %%mm4 \n\t"
+ "paddw %%mm7, %%mm4 \n\t"
+ "movq %%mm6, %%mm7 \n\t"
+ "paddw %%mm6, %%mm6 \n\t"
+ "paddw %%mm7, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "psrlw $3, %%mm4 \n\t"
+ "psrlw $3, %%mm6 \n\t"
+ "packuswb %%mm4, %%mm4 \n\t"
+ "packuswb %%mm6, %%mm6 \n\t"
+ "punpcklbw %%mm6, %%mm4 \n\t"
+ "punpcklbw %%mm4, %%mm1 \n\t"
+ "punpckhbw %%mm4, %%mm2 \n\t"
+
+ "add $16, %%"REG_S" \n\t"
+ "add $8, %%"REG_a" \n\t"
+ "add $8, %%"REG_b" \n\t"
+
+ "movq %%mm1, 16(%%"REG_D") \n\t"
+ "movq %%mm2, 24(%%"REG_D") \n\t"
+ "add $32, %%"REG_D" \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz .Lli1 \n\t"
+ "emms \n\t"
+ "pop %%"REG_BP" \n\t"
+ :
+ : "S" (y), "D" (dst), "a" (u), "b" (v), "c" (w/16),
+#if ARCH_X86_64
+ "d" ((x86_reg)us), "r" ((x86_reg)vs)
+#else
+ "d" (&us)
+#endif
+ : "memory"
+ );
+ pack_li_1_C(dst, y, u, v, (w&15), us, vs);
+}
+#endif /* HAVE_EBX_AVAILABLE */
+#endif
+
+static pack_func_t *pack_nn;
+static pack_func_t *pack_li_0;
+static pack_func_t *pack_li_1;
+
+static void ilpack(unsigned char *dst, unsigned char *src[3],
+ int dststride, int srcstride[3], int w, int h, pack_func_t *pack[2])
+{
+ int i;
+ unsigned char *y, *u, *v;
+ int ys = srcstride[0], us = srcstride[1], vs = srcstride[2];
+ int a, b;
+
+ y = src[0];
+ u = src[1];
+ v = src[2];
+
+ pack_nn(dst, y, u, v, w, 0, 0);
+ y += ys; dst += dststride;
+ pack_nn(dst, y, u+us, v+vs, w, 0, 0);
+ y += ys; dst += dststride;
+ for (i=2; i<h-2; i++) {
+ a = (i&2) ? 1 : -1;
+ b = (i&1) ^ ((i&2)>>1);
+ pack[b](dst, y, u, v, w, us*a, vs*a);
+ y += ys;
+ if ((i&3) == 1) {
+ u -= us;
+ v -= vs;
+ } else {
+ u += us;
+ v += vs;
+ }
+ dst += dststride;
+ }
+ pack_nn(dst, y, u, v, w, 0, 0);
+ y += ys; dst += dststride; u += us; v += vs;
+ pack_nn(dst, y, u, v, w, 0, 0);
+}
+
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next, IMGFMT_YUY2,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w, mpi->h);
+
+ ilpack(dmpi->planes[0], mpi->planes, dmpi->stride[0], mpi->stride, mpi->w, mpi->h, vf->priv->pack);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ /* FIXME - also support UYVY output? */
+ return vf_next_config(vf, width, height, d_width, d_height, flags, IMGFMT_YUY2);
+}
+
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - really any YUV 4:2:0 input format should work */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf,IMGFMT_YUY2);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->config=config;
+ vf->query_format=query_format;
+ vf->put_image=put_image;
+ vf->priv = calloc(1, sizeof(struct vf_priv_s));
+ vf->priv->mode = 1;
+ if (args) sscanf(args, "%d", &vf->priv->mode);
+
+ pack_nn = (pack_func_t *)pack_nn_C;
+ pack_li_0 = pack_li_0_C;
+ pack_li_1 = pack_li_1_C;
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX) {
+ pack_nn = (pack_func_t *)pack_nn_MMX;
+#if HAVE_EBX_AVAILABLE
+ pack_li_0 = pack_li_0_MMX;
+ pack_li_1 = pack_li_1_MMX;
+#endif
+ }
+#endif
+
+ switch(vf->priv->mode) {
+ case 0:
+ vf->priv->pack[0] = vf->priv->pack[1] = pack_nn;
+ break;
+ default:
+ mp_msg(MSGT_VFILTER, MSGL_WARN,
+ "ilpack: unknown mode %d (fallback to linear)\n",
+ vf->priv->mode);
+ case 1:
+ vf->priv->pack[0] = pack_li_0;
+ vf->priv->pack[1] = pack_li_1;
+ break;
+ }
+
+ return 1;
+}
+
+const vf_info_t vf_info_ilpack = {
+ "4:2:0 planar -> 4:2:2 packed reinterlacer",
+ "ilpack",
+ "Richard Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_ivtc.c b/libavfilter/libmpcodecs/vf_ivtc.c
new file mode 100644
index 0000000000..b10e50561a
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_ivtc.c
@@ -0,0 +1,550 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+
+struct metrics {
+ /* difference: total, even lines, odd lines */
+ int d, e, o;
+ /* noise: temporal, spacial (current), spacial (past) */
+ int t, s, p;
+};
+
+struct frameinfo {
+ /* peak, relative, mean */
+ struct metrics p, r, m;
+};
+
+struct vf_priv_s {
+ struct frameinfo fi[2];
+ mp_image_t *dmpi;
+ int first;
+ int drop, lastdrop, dropnext;
+ int inframes, outframes;
+};
+
+enum {
+ F_DROP,
+ F_MERGE,
+ F_NEXT,
+ F_SHOW
+};
+
+#if HAVE_MMX && HAVE_EBX_AVAILABLE
+static void block_diffs_MMX(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
+{
+ int i;
+ short out[24]; // output buffer for the partial metrics from the mmx code
+
+ __asm__ (
+ "movl $4, %%ecx \n\t"
+ "pxor %%mm4, %%mm4 \n\t" // 4 even difference sums
+ "pxor %%mm5, %%mm5 \n\t" // 4 odd difference sums
+ "pxor %%mm7, %%mm7 \n\t" // all zeros
+
+ ASMALIGN(4)
+ "1: \n\t"
+
+ // Even difference
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "movq (%%"REG_D"), %%mm1 \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "psubusb %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm0, %%mm4 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "paddw %%mm3, %%mm4 \n\t"
+
+ // Odd difference
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S"), %%mm2 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "movq (%%"REG_D"), %%mm1 \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "psubusb %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm0, %%mm5 \n\t"
+ "paddw %%mm1, %%mm5 \n\t"
+ "paddw %%mm2, %%mm5 \n\t"
+ "paddw %%mm3, %%mm5 \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz 1b \n\t"
+ "movq %%mm4, (%%"REG_d") \n\t"
+ "movq %%mm5, 8(%%"REG_d") \n\t"
+ :
+ : "S" (old), "D" (new), "a" (os), "b" (ns), "d" (out)
+ : "memory"
+ );
+ m->e = out[0]+out[1]+out[2]+out[3];
+ m->o = out[4]+out[5]+out[6]+out[7];
+ m->d = m->e + m->o;
+
+ __asm__ (
+ // First loop to measure first four columns
+ "movl $4, %%ecx \n\t"
+ "pxor %%mm4, %%mm4 \n\t" // Past spacial noise
+ "pxor %%mm5, %%mm5 \n\t" // Temporal noise
+ "pxor %%mm6, %%mm6 \n\t" // Current spacial noise
+
+ ASMALIGN(4)
+ "2: \n\t"
+
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "movq (%%"REG_D"), %%mm2 \n\t"
+ "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm1, %%mm5 \n\t"
+ "paddw %%mm3, %%mm6 \n\t"
+ "psubw %%mm0, %%mm4 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+ "psubw %%mm2, %%mm6 \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz 2b \n\t"
+
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "movq %%mm0, %%mm3 \n\t"
+ "pcmpgtw %%mm4, %%mm1 \n\t"
+ "pcmpgtw %%mm5, %%mm2 \n\t"
+ "pcmpgtw %%mm6, %%mm3 \n\t"
+ "pxor %%mm1, %%mm4 \n\t"
+ "pxor %%mm2, %%mm5 \n\t"
+ "pxor %%mm3, %%mm6 \n\t"
+ "psubw %%mm1, %%mm4 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+ "psubw %%mm3, %%mm6 \n\t"
+ "movq %%mm4, (%%"REG_d") \n\t"
+ "movq %%mm5, 16(%%"REG_d") \n\t"
+ "movq %%mm6, 32(%%"REG_d") \n\t"
+
+ "mov %%"REG_a", %%"REG_c" \n\t"
+ "shl $3, %%"REG_c" \n\t"
+ "sub %%"REG_c", %%"REG_S" \n\t"
+ "mov %%"REG_b", %%"REG_c" \n\t"
+ "shl $3, %%"REG_c" \n\t"
+ "sub %%"REG_c", %%"REG_D" \n\t"
+
+ // Second loop for the last four columns
+ "movl $4, %%ecx \n\t"
+ "pxor %%mm4, %%mm4 \n\t"
+ "pxor %%mm5, %%mm5 \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+
+ ASMALIGN(4)
+ "3: \n\t"
+
+ "movq (%%"REG_S"), %%mm0 \n\t"
+ "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "add %%"REG_a", %%"REG_S" \n\t"
+ "movq (%%"REG_D"), %%mm2 \n\t"
+ "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "add %%"REG_b", %%"REG_D" \n\t"
+ "punpckhbw %%mm7, %%mm0 \n\t"
+ "punpckhbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm1, %%mm5 \n\t"
+ "paddw %%mm3, %%mm6 \n\t"
+ "psubw %%mm0, %%mm4 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+ "psubw %%mm2, %%mm6 \n\t"
+
+ "decl %%ecx \n\t"
+ "jnz 3b \n\t"
+
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "movq %%mm0, %%mm3 \n\t"
+ "pcmpgtw %%mm4, %%mm1 \n\t"
+ "pcmpgtw %%mm5, %%mm2 \n\t"
+ "pcmpgtw %%mm6, %%mm3 \n\t"
+ "pxor %%mm1, %%mm4 \n\t"
+ "pxor %%mm2, %%mm5 \n\t"
+ "pxor %%mm3, %%mm6 \n\t"
+ "psubw %%mm1, %%mm4 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+ "psubw %%mm3, %%mm6 \n\t"
+ "movq %%mm4, 8(%%"REG_d") \n\t"
+ "movq %%mm5, 24(%%"REG_d") \n\t"
+ "movq %%mm6, 40(%%"REG_d") \n\t"
+
+ "emms \n\t"
+ :
+ : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out)
+ : "memory"
+ );
+ m->p = m->t = m->s = 0;
+ for (i=0; i<8; i++) {
+ m->p += out[i];
+ m->t += out[8+i];
+ m->s += out[16+i];
+ }
+ //printf("e=%d o=%d d=%d p=%d t=%d s=%d\n", m->e, m->o, m->d, m->p, m->t, m->s);
+}
+#endif
+
+//#define MAG(a) ((a)*(a))
+//#define MAG(a) (abs(a))
+#define MAG(a) (((a)^((a)>>31))-((a)>>31))
+
+//#define LOWPASS(s) (((s)[-2] + 4*(s)[-1] + 6*(s)[0] + 4*(s)[1] + (s)[2])>>4)
+//#define LOWPASS(s) (((s)[-1] + 2*(s)[0] + (s)[1])>>2)
+#define LOWPASS(s) ((s)[0])
+
+
+static void block_diffs_C(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
+{
+ int x, y, e=0, o=0, s=0, p=0, t=0;
+ unsigned char *oldp, *newp;
+ m->s = m->p = m->t = 0;
+ for (x = 8; x; x--) {
+ oldp = old++;
+ newp = new++;
+ s = p = t = 0;
+ for (y = 4; y; y--) {
+ e += MAG(newp[0]-oldp[0]);
+ o += MAG(newp[ns]-oldp[os]);
+ s += newp[ns]-newp[0];
+ p += oldp[os]-oldp[0];
+ t += oldp[os]-newp[0];
+ oldp += os<<1;
+ newp += ns<<1;
+ }
+ m->s += MAG(s);
+ m->p += MAG(p);
+ m->t += MAG(t);
+ }
+ m->e = e;
+ m->o = o;
+ m->d = e+o;
+}
+
+static void (*block_diffs)(struct metrics *, unsigned char *, unsigned char *, int, int);
+
+#define MAXUP(a,b) ((a) = ((a)>(b)) ? (a) : (b))
+
+static void diff_planes(struct frameinfo *fi,
+ unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
+{
+ int x, y;
+ struct metrics l;
+ struct metrics *peak=&fi->p, *rel=&fi->r, *mean=&fi->m;
+ memset(peak, 0, sizeof(struct metrics));
+ memset(rel, 0, sizeof(struct metrics));
+ memset(mean, 0, sizeof(struct metrics));
+ for (y = 0; y < h-7; y += 8) {
+ for (x = 8; x < w-8-7; x += 8) {
+ block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns);
+ mean->d += l.d;
+ mean->e += l.e;
+ mean->o += l.o;
+ mean->s += l.s;
+ mean->p += l.p;
+ mean->t += l.t;
+ MAXUP(peak->d, l.d);
+ MAXUP(peak->e, l.e);
+ MAXUP(peak->o, l.o);
+ MAXUP(peak->s, l.s);
+ MAXUP(peak->p, l.p);
+ MAXUP(peak->t, l.t);
+ MAXUP(rel->e, l.e-l.o);
+ MAXUP(rel->o, l.o-l.e);
+ MAXUP(rel->s, l.s-l.t);
+ MAXUP(rel->p, l.p-l.t);
+ MAXUP(rel->t, l.t-l.p);
+ MAXUP(rel->d, l.t-l.s); /* hack */
+ }
+ }
+ x = (w/8-2)*(h/8);
+ mean->d /= x;
+ mean->e /= x;
+ mean->o /= x;
+ mean->s /= x;
+ mean->p /= x;
+ mean->t /= x;
+}
+
+static void diff_fields(struct frameinfo *fi, mp_image_t *old, mp_image_t *new)
+{
+ diff_planes(fi, old->planes[0], new->planes[0],
+ new->w, new->h, old->stride[0], new->stride[0]);
+}
+
+static void stats(struct frameinfo *f)
+{
+ mp_msg(MSGT_VFILTER, MSGL_V, " pd=%d re=%d ro=%d rp=%d rt=%d rs=%d rd=%d pp=%d pt=%d ps=%d\r",
+ f->p.d, f->r.e, f->r.o, f->r.p, f->r.t, f->r.s, f->r.d, f->p.p, f->p.t, f->p.s);
+}
+
+static int foo(struct vf_priv_s *p, mp_image_t *new, mp_image_t *cur)
+{
+ struct frameinfo *f = p->fi;
+
+ f[0] = f[1];
+ diff_fields(&f[1], cur, new);
+ stats(&f[1]);
+
+ // Immediately drop this frame if it's already been used.
+ if (p->dropnext) {
+ p->dropnext = 0;
+ return F_DROP;
+ }
+
+ // Sometimes a pulldown frame comes all by itself, so both
+ // its top and bottom field are duplicates from the adjacent
+ // two frames. We can just drop such a frame, but we
+ // immediately show the next frame instead to keep the frame
+ // drops evenly spaced during normal 3:2 pulldown sequences.
+ if ((3*f[1].r.o < f[1].r.e) && (f[1].r.s < f[1].r.d)) {
+ p->dropnext = 1;
+ return F_NEXT;
+ }
+
+ // If none of these conditions hold, we will consider the frame
+ // progressive and just show it as-is.
+ if (!( (3*f[0].r.e < f[0].r.o) ||
+ ((2*f[0].r.d < f[0].r.s) && (f[0].r.s > 1200)) ||
+ ((2*f[1].r.t < f[1].r.p) && (f[1].r.p > 1200)) ))
+ return F_SHOW;
+
+ // Otherwise, we have to decide whether to merge or drop.
+ // If the noise metric only increases minimally, we're off
+ // to a good start...
+ if (((2*f[1].r.t < 3*f[1].r.p) && (f[1].r.t < 3600)) ||
+ (f[1].r.t < 900) || (f[1].r.d < 900)) {
+ // ...and if noise decreases or the duplicate even field
+ // is detected, we go ahead with the merge.
+ if ((3*f[0].r.e < f[0].r.o) || (2*f[1].r.t < f[1].r.p)) {
+ p->dropnext = 1;
+ return F_MERGE;
+ }
+ }
+ return F_DROP;
+}
+
+
+
+static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field)
+{
+ switch (field) {
+ case 0:
+ my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ break;
+ case 1:
+ my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
+ mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
+ mpi->planes[1]+mpi->stride[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
+ mpi->planes[2]+mpi->stride[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ break;
+ case 2:
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0], mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2], mpi->stride[2]);
+ }
+ break;
+ }
+}
+
+static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi)
+{
+ struct vf_priv_s *p = vf->priv;
+ int dropflag=0;
+
+ if (!p->dropnext) switch (p->drop) {
+ case 0:
+ dropflag = 0;
+ break;
+ case 1:
+ dropflag = (++p->lastdrop >= 5);
+ break;
+ case 2:
+ dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes);
+ break;
+ }
+
+ if (dropflag) {
+ //mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n",
+ // p->outframes, p->inframes, (float)p->outframes/p->inframes);
+ mp_msg(MSGT_VFILTER, MSGL_V, "!");
+ p->lastdrop = 0;
+ return 0;
+ }
+
+ p->outframes++;
+ return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ int ret=0;
+ struct vf_priv_s *p = vf->priv;
+
+ p->inframes++;
+
+ if (p->first) { /* hack */
+ p->first = 0;
+ return 1;
+ }
+
+ if (!p->dmpi) p->dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
+ mpi->width, mpi->height);
+ /* FIXME -- not correct, off by one frame! */
+ p->dmpi->qscale = mpi->qscale;
+ p->dmpi->qstride = mpi->qstride;
+ p->dmpi->qscale_type = mpi->qscale_type;
+
+ switch (foo(p, mpi, p->dmpi)) {
+ case F_DROP:
+ copy_image(p->dmpi, mpi, 2);
+ ret = 0;
+ p->lastdrop = 0;
+ mp_msg(MSGT_VFILTER, MSGL_V, "DROP\n");
+ break;
+ case F_MERGE:
+ copy_image(p->dmpi, mpi, 0);
+ ret = do_put_image(vf, p->dmpi);
+ copy_image(p->dmpi, mpi, 1);
+ mp_msg(MSGT_VFILTER, MSGL_V, "MERGE\n");
+ p->dmpi = NULL;
+ break;
+ case F_NEXT:
+ copy_image(p->dmpi, mpi, 2);
+ ret = do_put_image(vf, p->dmpi);
+ mp_msg(MSGT_VFILTER, MSGL_V, "NEXT\n");
+ p->dmpi = NULL;
+ break;
+ case F_SHOW:
+ ret = do_put_image(vf, p->dmpi);
+ copy_image(p->dmpi, mpi, 2);
+ mp_msg(MSGT_VFILTER, MSGL_V, "OK\n");
+ p->dmpi = NULL;
+ break;
+ }
+ return ret;
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ vf->put_image = put_image;
+ vf->query_format = query_format;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ p->drop = 0;
+ p->first = 1;
+ if (args) sscanf(args, "%d", &p->drop);
+ block_diffs = block_diffs_C;
+#if HAVE_MMX && HAVE_EBX_AVAILABLE
+ if(gCpuCaps.hasMMX) block_diffs = block_diffs_MMX;
+#endif
+ return 1;
+}
+
+const vf_info_t vf_info_ivtc = {
+ "inverse telecine, take 2",
+ "ivtc",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_kerndeint.c b/libavfilter/libmpcodecs/vf_kerndeint.c
new file mode 100644
index 0000000000..c5197fc542
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_kerndeint.c
@@ -0,0 +1,345 @@
+/*
+ * Original AVISynth Filter Copyright (C) 2003 Donald A. Graft
+ * Adapted to MPlayer by Tobias Diedrich
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "mp_msg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+
+//===========================================================================//
+
+struct vf_priv_s {
+ int frame;
+ int map;
+ int order;
+ int thresh;
+ int sharp;
+ int twoway;
+ int do_deinterlace;
+};
+
+
+/***************************************************************************/
+
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static inline int IsRGB(mp_image_t *mpi)
+{
+ return mpi->imgfmt == IMGFMT_RGB;
+}
+
+static inline int IsYUY2(mp_image_t *mpi)
+{
+ return mpi->imgfmt == IMGFMT_YUY2;
+}
+
+#define PLANAR_Y 0
+#define PLANAR_U 1
+#define PLANAR_V 2
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+ int W = mpi->w, H = mpi->h;
+ const unsigned char *prvp, *prvpp, *prvpn, *prvpnn, *prvppp, *prvp4p, *prvp4n;
+ const unsigned char *srcp_saved;
+ const unsigned char *srcp, *srcpp, *srcpn, *srcpnn, *srcppp, *srcp3p, *srcp3n, *srcp4p, *srcp4n;
+ unsigned char *dstp, *dstp_saved;
+ int src_pitch;
+ int psrc_pitch;
+ int dst_pitch;
+ int x, y, z;
+ int n = vf->priv->frame++;
+ int val, hi, lo, w, h;
+ double valf;
+ int plane;
+ int threshold = vf->priv->thresh;
+ int order = vf->priv->order;
+ int map = vf->priv->map;
+ int sharp = vf->priv->sharp;
+ int twoway = vf->priv->twoway;
+ mp_image_t *dmpi, *pmpi;
+
+ if(!vf->priv->do_deinterlace)
+ return vf_next_put_image(vf, mpi, pts);
+
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+ pmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+ if(!dmpi) return 0;
+
+ for (z=0; z<mpi->num_planes; z++) {
+ if (z == 0) plane = PLANAR_Y;
+ else if (z == 1) plane = PLANAR_U;
+ else plane = PLANAR_V;
+
+ h = plane == PLANAR_Y ? H : ch;
+ w = plane == PLANAR_Y ? W : cw;
+
+ srcp = srcp_saved = mpi->planes[z];
+ src_pitch = mpi->stride[z];
+ psrc_pitch = pmpi->stride[z];
+ dstp = dstp_saved = dmpi->planes[z];
+ dst_pitch = dmpi->stride[z];
+ srcp = srcp_saved + (1-order) * src_pitch;
+ dstp = dstp_saved + (1-order) * dst_pitch;
+
+ for (y=0; y<h; y+=2) {
+ fast_memcpy(dstp, srcp, w);
+ srcp += 2*src_pitch;
+ dstp += 2*dst_pitch;
+ }
+
+ // Copy through the lines that will be missed below.
+ fast_memcpy(dstp_saved + order*dst_pitch, srcp_saved + (1-order)*src_pitch, w);
+ fast_memcpy(dstp_saved + (2+order)*dst_pitch, srcp_saved + (3-order)*src_pitch, w);
+ fast_memcpy(dstp_saved + (h-2+order)*dst_pitch, srcp_saved + (h-1-order)*src_pitch, w);
+ fast_memcpy(dstp_saved + (h-4+order)*dst_pitch, srcp_saved + (h-3-order)*src_pitch, w);
+ /* For the other field choose adaptively between using the previous field
+ or the interpolant from the current field. */
+
+ prvp = pmpi->planes[z] + 5*psrc_pitch - (1-order)*psrc_pitch;
+ prvpp = prvp - psrc_pitch;
+ prvppp = prvp - 2*psrc_pitch;
+ prvp4p = prvp - 4*psrc_pitch;
+ prvpn = prvp + psrc_pitch;
+ prvpnn = prvp + 2*psrc_pitch;
+ prvp4n = prvp + 4*psrc_pitch;
+ srcp = srcp_saved + 5*src_pitch - (1-order)*src_pitch;
+ srcpp = srcp - src_pitch;
+ srcppp = srcp - 2*src_pitch;
+ srcp3p = srcp - 3*src_pitch;
+ srcp4p = srcp - 4*src_pitch;
+ srcpn = srcp + src_pitch;
+ srcpnn = srcp + 2*src_pitch;
+ srcp3n = srcp + 3*src_pitch;
+ srcp4n = srcp + 4*src_pitch;
+ dstp = dstp_saved + 5*dst_pitch - (1-order)*dst_pitch;
+ for (y = 5 - (1-order); y <= h - 5 - (1-order); y+=2)
+ {
+ for (x = 0; x < w; x++)
+ {
+ if ((threshold == 0) || (n == 0) ||
+ (abs((int)prvp[x] - (int)srcp[x]) > threshold) ||
+ (abs((int)prvpp[x] - (int)srcpp[x]) > threshold) ||
+ (abs((int)prvpn[x] - (int)srcpn[x]) > threshold))
+ {
+ if (map == 1)
+ {
+ int g = x & ~3;
+ if (IsRGB(mpi) == 1)
+ {
+ dstp[g++] = 255;
+ dstp[g++] = 255;
+ dstp[g++] = 255;
+ dstp[g] = 255;
+ x = g;
+ }
+ else if (IsYUY2(mpi) == 1)
+ {
+ dstp[g++] = 235;
+ dstp[g++] = 128;
+ dstp[g++] = 235;
+ dstp[g] = 128;
+ x = g;
+ }
+ else
+ {
+ if (plane == PLANAR_Y) dstp[x] = 235;
+ else dstp[x] = 128;
+ }
+ }
+ else
+ {
+ if (IsRGB(mpi))
+ {
+ hi = 255;
+ lo = 0;
+ }
+ else if (IsYUY2(mpi))
+ {
+ hi = (x & 1) ? 240 : 235;
+ lo = 16;
+ }
+ else
+ {
+ hi = (plane == PLANAR_Y) ? 235 : 240;
+ lo = 16;
+ }
+
+ if (sharp == 1)
+ {
+ if (twoway == 1)
+ valf = + 0.526*((int)srcpp[x] + (int)srcpn[x])
+ + 0.170*((int)srcp[x] + (int)prvp[x])
+ - 0.116*((int)srcppp[x] + (int)srcpnn[x] + (int)prvppp[x] + (int)prvpnn[x])
+ - 0.026*((int)srcp3p[x] + (int)srcp3n[x])
+ + 0.031*((int)srcp4p[x] + (int)srcp4n[x] + (int)prvp4p[x] + (int)prvp4n[x]);
+ else
+ valf = + 0.526*((int)srcpp[x] + (int)srcpn[x])
+ + 0.170*((int)prvp[x])
+ - 0.116*((int)prvppp[x] + (int)prvpnn[x])
+ - 0.026*((int)srcp3p[x] + (int)srcp3n[x])
+ + 0.031*((int)prvp4p[x] + (int)prvp4p[x]);
+ if (valf > hi) valf = hi;
+ else if (valf < lo) valf = lo;
+ dstp[x] = (int) valf;
+ }
+ else
+ {
+ if (twoway == 1)
+ val = (8*((int)srcpp[x] + (int)srcpn[x]) + 2*((int)srcp[x] + (int)prvp[x]) -
+ (int)(srcppp[x]) - (int)(srcpnn[x]) -
+ (int)(prvppp[x]) - (int)(prvpnn[x])) >> 4;
+ else
+ val = (8*((int)srcpp[x] + (int)srcpn[x]) + 2*((int)prvp[x]) -
+ (int)(prvppp[x]) - (int)(prvpnn[x])) >> 4;
+ if (val > hi) val = hi;
+ else if (val < lo) val = lo;
+ dstp[x] = (int) val;
+ }
+ }
+ }
+ else
+ {
+ dstp[x] = srcp[x];
+ }
+ }
+ prvp += 2*psrc_pitch;
+ prvpp += 2*psrc_pitch;
+ prvppp += 2*psrc_pitch;
+ prvpn += 2*psrc_pitch;
+ prvpnn += 2*psrc_pitch;
+ prvp4p += 2*psrc_pitch;
+ prvp4n += 2*psrc_pitch;
+ srcp += 2*src_pitch;
+ srcpp += 2*src_pitch;
+ srcppp += 2*src_pitch;
+ srcp3p += 2*src_pitch;
+ srcp4p += 2*src_pitch;
+ srcpn += 2*src_pitch;
+ srcpnn += 2*src_pitch;
+ srcp3n += 2*src_pitch;
+ srcp4n += 2*src_pitch;
+ dstp += 2*dst_pitch;
+ }
+
+ srcp = mpi->planes[z];
+ dstp = pmpi->planes[z];
+ for (y=0; y<h; y++) {
+ fast_memcpy(dstp, srcp, w);
+ srcp += src_pitch;
+ dstp += psrc_pitch;
+ }
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_RGB:
+ case IMGFMT_YUY2:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int control(struct vf_instance *vf, int request, void* data){
+ switch (request)
+ {
+ case VFCTRL_GET_DEINTERLACE:
+ *(int*)data = vf->priv->do_deinterlace;
+ return CONTROL_OK;
+ case VFCTRL_SET_DEINTERLACE:
+ vf->priv->do_deinterlace = *(int*)data;
+ return CONTROL_OK;
+ }
+ return vf_next_control (vf, request, data);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+
+ vf->control=control;
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ vf->priv->frame = 0;
+
+ vf->priv->map = 0;
+ vf->priv->order = 0;
+ vf->priv->thresh = 10;
+ vf->priv->sharp = 0;
+ vf->priv->twoway = 0;
+ vf->priv->do_deinterlace=1;
+
+ if (args)
+ {
+ sscanf(args, "%d:%d:%d:%d:%d",
+ &vf->priv->thresh, &vf->priv->map,
+ &vf->priv->order, &vf->priv->sharp,
+ &vf->priv->twoway);
+ }
+ if (vf->priv->order > 1) vf->priv->order = 1;
+
+ return 1;
+}
+
+const vf_info_t vf_info_kerndeint = {
+ "Kernel Deinterlacer",
+ "kerndeint",
+ "Donald Graft",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_mcdeint.c b/libavfilter/libmpcodecs/vf_mcdeint.c
new file mode 100644
index 0000000000..aad2afdfad
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_mcdeint.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+/*
+Known Issues:
+* The motion estimation is somewhat at the mercy of the input, if the input
+ frames are created purely based on spatial interpolation then for example
+ a thin black line or another random and not interpolateable pattern
+ will cause problems
+ Note: completly ignoring the "unavailable" lines during motion estimation
+ didnt look any better, so the most obvious solution would be to improve
+ tfields or penalize problematic motion vectors ...
+
+* If non iterative ME is used then snow currently ignores the OBMC window
+ and as a result sometimes creates artifacts
+
+* only past frames are used, we should ideally use future frames too, something
+ like filtering the whole movie in forward and then backward direction seems
+ like a interresting idea but the current filter framework is FAR from
+ supporting such things
+
+* combining the motion compensated image with the input image also isnt
+ as trivial as it seems, simple blindly taking even lines from one and
+ odd ones from the other doesnt work at all as ME/MC sometimes simple
+ has nothing in the previous frames which matches the current, the current
+ algo has been found by trial and error and almost certainly can be
+ improved ...
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavcodec/avcodec.h"
+#include "libavcodec/dsputil.h"
+
+#undef fprintf
+#undef free
+#undef malloc
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "vd_ffmpeg.h"
+
+#define MIN(a,b) ((a) > (b) ? (b) : (a))
+#define MAX(a,b) ((a) < (b) ? (b) : (a))
+#define ABS(a) ((a) > 0 ? (a) : (-(a)))
+
+//===========================================================================//
+
+struct vf_priv_s {
+ int mode;
+ int qp;
+ int parity;
+#if 0
+ int temp_stride[3];
+ uint8_t *src[3];
+ int16_t *temp[3];
+#endif
+ int outbuf_size;
+ uint8_t *outbuf;
+ AVCodecContext *avctx_enc;
+ AVFrame *frame;
+ AVFrame *frame_dec;
+};
+
+static void filter(struct vf_priv_s *p, uint8_t *dst[3], uint8_t *src[3], int dst_stride[3], int src_stride[3], int width, int height){
+ int x, y, i;
+ int out_size;
+
+ for(i=0; i<3; i++){
+ p->frame->data[i]= src[i];
+ p->frame->linesize[i]= src_stride[i];
+ }
+
+ p->avctx_enc->me_cmp=
+ p->avctx_enc->me_sub_cmp= FF_CMP_SAD /*| (p->parity ? FF_CMP_ODD : FF_CMP_EVEN)*/;
+ p->frame->quality= p->qp*FF_QP2LAMBDA;
+ out_size = avcodec_encode_video(p->avctx_enc, p->outbuf, p->outbuf_size, p->frame);
+ p->frame_dec = p->avctx_enc->coded_frame;
+
+ for(i=0; i<3; i++){
+ int is_chroma= !!i;
+ int w= width >>is_chroma;
+ int h= height>>is_chroma;
+ int fils= p->frame_dec->linesize[i];
+ int srcs= src_stride[i];
+
+ for(y=0; y<h; y++){
+ if((y ^ p->parity) & 1){
+ for(x=0; x<w; x++){
+ if((x-2)+(y-1)*w>=0 && (x+2)+(y+1)*w<w*h){ //FIXME either alloc larger images or optimize this
+ uint8_t *filp= &p->frame_dec->data[i][x + y*fils];
+ uint8_t *srcp= &src[i][x + y*srcs];
+ int diff0= filp[-fils] - srcp[-srcs];
+ int diff1= filp[+fils] - srcp[+srcs];
+ int spatial_score= ABS(srcp[-srcs-1] - srcp[+srcs-1])
+ +ABS(srcp[-srcs ] - srcp[+srcs ])
+ +ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
+ int temp= filp[0];
+
+#define CHECK(j)\
+ { int score= ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
+ + ABS(srcp[-srcs +j] - srcp[+srcs -j])\
+ + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
+ if(score < spatial_score){\
+ spatial_score= score;\
+ diff0= filp[-fils+j] - srcp[-srcs+j];\
+ diff1= filp[+fils-j] - srcp[+srcs-j];
+
+ CHECK(-1) CHECK(-2) }} }}
+ CHECK( 1) CHECK( 2) }} }}
+#if 0
+ if((diff0 ^ diff1) > 0){
+ int mindiff= ABS(diff0) > ABS(diff1) ? diff1 : diff0;
+ temp-= mindiff;
+ }
+#elif 1
+ if(diff0 + diff1 > 0)
+ temp-= (diff0 + diff1 - ABS( ABS(diff0) - ABS(diff1) )/2)/2;
+ else
+ temp-= (diff0 + diff1 + ABS( ABS(diff0) - ABS(diff1) )/2)/2;
+#else
+ temp-= (diff0 + diff1)/2;
+#endif
+#if 1
+ filp[0]=
+ dst[i][x + y*dst_stride[i]]= temp > 255U ? ~(temp>>31) : temp;
+#else
+ dst[i][x + y*dst_stride[i]]= filp[0];
+ filp[0]= temp > 255U ? ~(temp>>31) : temp;
+#endif
+ }else
+ dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
+ }
+ }
+ }
+ for(y=0; y<h; y++){
+ if(!((y ^ p->parity) & 1)){
+ for(x=0; x<w; x++){
+#if 1
+ p->frame_dec->data[i][x + y*fils]=
+ dst[i][x + y*dst_stride[i]]= src[i][x + y*srcs];
+#else
+ dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
+ p->frame_dec->data[i][x + y*fils]= src[i][x + y*srcs];
+#endif
+ }
+ }
+ }
+ }
+ p->parity ^= 1;
+
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ int i;
+ AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
+
+ for(i=0; i<3; i++){
+ AVCodecContext *avctx_enc;
+#if 0
+ int is_chroma= !!i;
+ int w= ((width + 31) & (~31))>>is_chroma;
+ int h= ((height + 31) & (~31))>>is_chroma;
+
+ vf->priv->temp_stride[i]= w;
+ vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
+ vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
+#endif
+ avctx_enc=
+ vf->priv->avctx_enc= avcodec_alloc_context();
+ avctx_enc->width = width;
+ avctx_enc->height = height;
+ avctx_enc->time_base= (AVRational){1,25}; // meaningless
+ avctx_enc->gop_size = 300;
+ avctx_enc->max_b_frames= 0;
+ avctx_enc->pix_fmt = PIX_FMT_YUV420P;
+ avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
+ avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
+ avctx_enc->global_quality= 1;
+ avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY;
+ avctx_enc->me_cmp=
+ avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE;
+ avctx_enc->mb_cmp= FF_CMP_SSE;
+
+ switch(vf->priv->mode){
+ case 3:
+ avctx_enc->refs= 3;
+ case 2:
+ avctx_enc->me_method= ME_ITER;
+ case 1:
+ avctx_enc->flags |= CODEC_FLAG_4MV;
+ avctx_enc->dia_size=2;
+// avctx_enc->mb_decision = MB_DECISION_RD;
+ case 0:
+ avctx_enc->flags |= CODEC_FLAG_QPEL;
+ }
+
+ avcodec_open(avctx_enc, enc);
+
+ }
+ vf->priv->frame= avcodec_alloc_frame();
+
+ vf->priv->outbuf_size= width*height*10;
+ vf->priv->outbuf= malloc(vf->priv->outbuf_size);
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+return; //caused problems, dunno why
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->width,mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+ }else{
+ dmpi=vf->dmpi;
+ }
+
+ filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+#if 0
+ for(i=0; i<3; i++){
+ free(vf->priv->temp[i]);
+ vf->priv->temp[i]= NULL;
+ free(vf->priv->src[i]);
+ vf->priv->src[i]= NULL;
+ }
+#endif
+ if (vf->priv->avctx_enc) {
+ avcodec_close(vf->priv->avctx_enc);
+ av_freep(&vf->priv->avctx_enc);
+ }
+
+ free(vf->priv->outbuf);
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt){
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ init_avcodec();
+
+ vf->priv->mode=0;
+ vf->priv->parity= -1;
+ vf->priv->qp=1;
+
+ if (args) sscanf(args, "%d:%d:%d", &vf->priv->mode, &vf->priv->parity, &vf->priv->qp);
+
+ return 1;
+}
+
+const vf_info_t vf_info_mcdeint = {
+ "motion compensating deinterlacer",
+ "mcdeint",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_mirror.c b/libavfilter/libmpcodecs/vf_mirror.c
new file mode 100644
index 0000000000..5ac05e9145
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_mirror.c
@@ -0,0 +1,131 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+
+static void mirror(unsigned char* dst,unsigned char* src,int dststride,int srcstride,int w,int h,int bpp,unsigned int fmt){
+ int y;
+ for(y=0;y<h;y++){
+ int x;
+ switch(bpp){
+ case 1:
+ for(x=0;x<w;x++) dst[x]=src[w-x-1];
+ break;
+ case 2:
+ switch(fmt){
+ case IMGFMT_UYVY: {
+ // packed YUV is tricky. U,V are 32bpp while Y is 16bpp:
+ int w2=w>>1;
+ for(x=0;x<w2;x++){
+ // TODO: optimize this...
+ dst[x*4+0]=src[0+(w2-x-1)*4];
+ dst[x*4+1]=src[3+(w2-x-1)*4];
+ dst[x*4+2]=src[2+(w2-x-1)*4];
+ dst[x*4+3]=src[1+(w2-x-1)*4];
+ }
+ break; }
+ case IMGFMT_YUY2:
+ case IMGFMT_YVYU: {
+ // packed YUV is tricky. U,V are 32bpp while Y is 16bpp:
+ int w2=w>>1;
+ for(x=0;x<w2;x++){
+ // TODO: optimize this...
+ dst[x*4+0]=src[2+(w2-x-1)*4];
+ dst[x*4+1]=src[1+(w2-x-1)*4];
+ dst[x*4+2]=src[0+(w2-x-1)*4];
+ dst[x*4+3]=src[3+(w2-x-1)*4];
+ }
+ break; }
+ default:
+ for(x=0;x<w;x++) *((short*)(dst+x*2))=*((short*)(src+(w-x-1)*2));
+ }
+ break;
+ case 3:
+ for(x=0;x<w;x++){
+ dst[x*3+0]=src[0+(w-x-1)*3];
+ dst[x*3+1]=src[1+(w-x-1)*3];
+ dst[x*3+2]=src[2+(w-x-1)*3];
+ }
+ break;
+ case 4:
+ for(x=0;x<w;x++) *((int*)(dst+x*4))=*((int*)(src+(w-x-1)*4));
+ }
+ src+=srcstride;
+ dst+=dststride;
+ }
+}
+
+//===========================================================================//
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w, mpi->h);
+
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mirror(dmpi->planes[0],mpi->planes[0],
+ dmpi->stride[0],mpi->stride[0],
+ dmpi->w,dmpi->h,1,mpi->imgfmt);
+ mirror(dmpi->planes[1],mpi->planes[1],
+ dmpi->stride[1],mpi->stride[1],
+ dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,mpi->imgfmt);
+ mirror(dmpi->planes[2],mpi->planes[2],
+ dmpi->stride[2],mpi->stride[2],
+ dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,mpi->imgfmt);
+ } else {
+ mirror(dmpi->planes[0],mpi->planes[0],
+ dmpi->stride[0],mpi->stride[0],
+ dmpi->w,dmpi->h,dmpi->bpp>>3,mpi->imgfmt);
+ dmpi->planes[1]=mpi->planes[1]; // passthrough rgb8 palette
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int vf_open(vf_instance_t *vf, char *args){
+ //vf->config=config;
+ vf->put_image=put_image;
+ return 1;
+}
+
+const vf_info_t vf_info_mirror = {
+ "horizontal mirror",
+ "mirror",
+ "Eyck",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_noise.c b/libavfilter/libmpcodecs/vf_noise.c
new file mode 100644
index 0000000000..9521619aed
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_noise.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+#include "libavutil/mem.h"
+
+#define MAX_NOISE 4096
+#define MAX_SHIFT 1024
+#define MAX_RES (MAX_NOISE-MAX_SHIFT)
+
+//===========================================================================//
+
+static inline void lineNoise_C(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift);
+static inline void lineNoiseAvg_C(uint8_t *dst, uint8_t *src, int len, int8_t **shift);
+
+static void (*lineNoise)(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift)= lineNoise_C;
+static void (*lineNoiseAvg)(uint8_t *dst, uint8_t *src, int len, int8_t **shift)= lineNoiseAvg_C;
+
+typedef struct FilterParam{
+ int strength;
+ int uniform;
+ int temporal;
+ int quality;
+ int averaged;
+ int pattern;
+ int shiftptr;
+ int8_t *noise;
+ int8_t *prev_shift[MAX_RES][3];
+}FilterParam;
+
+struct vf_priv_s {
+ FilterParam lumaParam;
+ FilterParam chromaParam;
+ unsigned int outfmt;
+};
+
+static int nonTempRandShift_init;
+static int nonTempRandShift[MAX_RES];
+
+static int patt[4] = {
+ -1,0,1,0
+};
+
+#define RAND_N(range) ((int) ((double)range*rand()/(RAND_MAX+1.0)))
+static int8_t *initNoise(FilterParam *fp){
+ int strength= fp->strength;
+ int uniform= fp->uniform;
+ int averaged= fp->averaged;
+ int pattern= fp->pattern;
+ int8_t *noise= av_malloc(MAX_NOISE*sizeof(int8_t));
+ int i, j;
+
+ srand(123457);
+
+ for(i=0,j=0; i<MAX_NOISE; i++,j++)
+ {
+ if(uniform) {
+ if (averaged) {
+ if (pattern) {
+ noise[i]= (RAND_N(strength) - strength/2)/6
+ +patt[j%4]*strength*0.25/3;
+ } else {
+ noise[i]= (RAND_N(strength) - strength/2)/3;
+ }
+ } else {
+ if (pattern) {
+ noise[i]= (RAND_N(strength) - strength/2)/2
+ + patt[j%4]*strength*0.25;
+ } else {
+ noise[i]= RAND_N(strength) - strength/2;
+ }
+ }
+ } else {
+ double x1, x2, w, y1;
+ do {
+ x1 = 2.0 * rand()/(float)RAND_MAX - 1.0;
+ x2 = 2.0 * rand()/(float)RAND_MAX - 1.0;
+ w = x1 * x1 + x2 * x2;
+ } while ( w >= 1.0 );
+
+ w = sqrt( (-2.0 * log( w ) ) / w );
+ y1= x1 * w;
+ y1*= strength / sqrt(3.0);
+ if (pattern) {
+ y1 /= 2;
+ y1 += patt[j%4]*strength*0.35;
+ }
+ if (y1<-128) y1=-128;
+ else if(y1> 127) y1= 127;
+ if (averaged) y1 /= 3.0;
+ noise[i]= (int)y1;
+ }
+ if (RAND_N(6) == 0) j--;
+ }
+
+
+ for (i = 0; i < MAX_RES; i++)
+ for (j = 0; j < 3; j++)
+ fp->prev_shift[i][j] = noise + (rand()&(MAX_SHIFT-1));
+
+ if(!nonTempRandShift_init){
+ for(i=0; i<MAX_RES; i++){
+ nonTempRandShift[i]= rand()&(MAX_SHIFT-1);
+ }
+ nonTempRandShift_init = 1;
+ }
+
+ fp->noise= noise;
+ fp->shiftptr= 0;
+ return noise;
+}
+
+/***************************************************************************/
+
+#if HAVE_MMX
+static inline void lineNoise_MMX(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
+ x86_reg mmx_len= len&(~7);
+ noise+=shift;
+
+ __asm__ volatile(
+ "mov %3, %%"REG_a" \n\t"
+ "pcmpeqb %%mm7, %%mm7 \n\t"
+ "psllw $15, %%mm7 \n\t"
+ "packsswb %%mm7, %%mm7 \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%0, %%"REG_a"), %%mm0 \n\t"
+ "movq (%1, %%"REG_a"), %%mm1 \n\t"
+ "pxor %%mm7, %%mm0 \n\t"
+ "paddsb %%mm1, %%mm0 \n\t"
+ "pxor %%mm7, %%mm0 \n\t"
+ "movq %%mm0, (%2, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ :: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
+ : "%"REG_a
+ );
+ if(mmx_len!=len)
+ lineNoise_C(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
+}
+#endif
+
+//duplicate of previous except movntq
+#if HAVE_MMX2
+static inline void lineNoise_MMX2(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
+ x86_reg mmx_len= len&(~7);
+ noise+=shift;
+
+ __asm__ volatile(
+ "mov %3, %%"REG_a" \n\t"
+ "pcmpeqb %%mm7, %%mm7 \n\t"
+ "psllw $15, %%mm7 \n\t"
+ "packsswb %%mm7, %%mm7 \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%0, %%"REG_a"), %%mm0 \n\t"
+ "movq (%1, %%"REG_a"), %%mm1 \n\t"
+ "pxor %%mm7, %%mm0 \n\t"
+ "paddsb %%mm1, %%mm0 \n\t"
+ "pxor %%mm7, %%mm0 \n\t"
+ "movntq %%mm0, (%2, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ :: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
+ : "%"REG_a
+ );
+ if(mmx_len!=len)
+ lineNoise_C(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
+}
+#endif
+
+static inline void lineNoise_C(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
+ int i;
+ noise+= shift;
+ for(i=0; i<len; i++)
+ {
+ int v= src[i]+ noise[i];
+ if(v>255) dst[i]=255; //FIXME optimize
+ else if(v<0) dst[i]=0;
+ else dst[i]=v;
+ }
+}
+
+/***************************************************************************/
+
+#if HAVE_MMX
+static inline void lineNoiseAvg_MMX(uint8_t *dst, uint8_t *src, int len, int8_t **shift){
+ x86_reg mmx_len= len&(~7);
+
+ __asm__ volatile(
+ "mov %5, %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%1, %%"REG_a"), %%mm1 \n\t"
+ "movq (%0, %%"REG_a"), %%mm0 \n\t"
+ "paddb (%2, %%"REG_a"), %%mm1 \n\t"
+ "paddb (%3, %%"REG_a"), %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "punpcklbw %%mm0, %%mm0 \n\t"
+ "punpckhbw %%mm2, %%mm2 \n\t"
+ "punpcklbw %%mm1, %%mm1 \n\t"
+ "punpckhbw %%mm3, %%mm3 \n\t"
+ "pmulhw %%mm0, %%mm1 \n\t"
+ "pmulhw %%mm2, %%mm3 \n\t"
+ "paddw %%mm1, %%mm1 \n\t"
+ "paddw %%mm3, %%mm3 \n\t"
+ "paddw %%mm0, %%mm1 \n\t"
+ "paddw %%mm2, %%mm3 \n\t"
+ "psrlw $8, %%mm1 \n\t"
+ "psrlw $8, %%mm3 \n\t"
+ "packuswb %%mm3, %%mm1 \n\t"
+ "movq %%mm1, (%4, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ :: "r" (src+mmx_len), "r" (shift[0]+mmx_len), "r" (shift[1]+mmx_len), "r" (shift[2]+mmx_len),
+ "r" (dst+mmx_len), "g" (-mmx_len)
+ : "%"REG_a
+ );
+
+ if(mmx_len!=len){
+ int8_t *shift2[3]={shift[0]+mmx_len, shift[1]+mmx_len, shift[2]+mmx_len};
+ lineNoiseAvg_C(dst+mmx_len, src+mmx_len, len-mmx_len, shift2);
+ }
+}
+#endif
+
+static inline void lineNoiseAvg_C(uint8_t *dst, uint8_t *src, int len, int8_t **shift){
+ int i;
+ int8_t *src2= (int8_t*)src;
+
+ for(i=0; i<len; i++)
+ {
+ const int n= shift[0][i] + shift[1][i] + shift[2][i];
+ dst[i]= src2[i]+((n*src2[i])>>7);
+ }
+}
+
+/***************************************************************************/
+
+static void noise(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp){
+ int8_t *noise= fp->noise;
+ int y;
+ int shift=0;
+
+ if(!noise)
+ {
+ if(src==dst) return;
+
+ if(dstStride==srcStride) fast_memcpy(dst, src, srcStride*height);
+ else
+ {
+ for(y=0; y<height; y++)
+ {
+ fast_memcpy(dst, src, width);
+ dst+= dstStride;
+ src+= srcStride;
+ }
+ }
+ return;
+ }
+
+ for(y=0; y<height; y++)
+ {
+ if(fp->temporal) shift= rand()&(MAX_SHIFT -1);
+ else shift= nonTempRandShift[y];
+
+ if(fp->quality==0) shift&= ~7;
+ if (fp->averaged) {
+ lineNoiseAvg(dst, src, width, fp->prev_shift[y]);
+ fp->prev_shift[y][fp->shiftptr] = noise + shift;
+ } else {
+ lineNoise(dst, src, noise, width, shift);
+ }
+ dst+= dstStride;
+ src+= srcStride;
+ }
+ fp->shiftptr++;
+ if (fp->shiftptr == 3) fp->shiftptr = 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags, mpi->w, mpi->h);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+//printf("nodr\n");
+ }
+//else printf("dr\n");
+ dmpi= vf->dmpi;
+
+ noise(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam);
+ noise(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam);
+ noise(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam);
+
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
+#endif
+#if HAVE_MMX2
+ if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
+#endif
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ av_free(vf->priv->chromaParam.noise);
+ vf->priv->chromaParam.noise= NULL;
+
+ av_free(vf->priv->lumaParam.noise);
+ vf->priv->lumaParam.noise= NULL;
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ return vf_next_query_format(vf,vf->priv->outfmt);
+ }
+ return 0;
+}
+
+static void parse(FilterParam *fp, char* args){
+ char *pos;
+ char *max= strchr(args, ':');
+
+ if(!max) max= args + strlen(args);
+
+ fp->strength= atoi(args);
+ pos= strchr(args, 'u');
+ if(pos && pos<max) fp->uniform=1;
+ pos= strchr(args, 't');
+ if(pos && pos<max) fp->temporal=1;
+ pos= strchr(args, 'h');
+ if(pos && pos<max) fp->quality=1;
+ pos= strchr(args, 'p');
+ if(pos && pos<max) fp->pattern=1;
+ pos= strchr(args, 'a');
+ if(pos && pos<max) {
+ fp->temporal=1;
+ fp->averaged=1;
+ }
+
+ if(fp->strength) initNoise(fp);
+}
+
+static const unsigned int fmt_list[]={
+ IMGFMT_YV12,
+ IMGFMT_I420,
+ IMGFMT_IYUV,
+ 0
+};
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+ if(args)
+ {
+ char *arg2= strchr(args,':');
+ if(arg2) parse(&vf->priv->chromaParam, arg2+1);
+ parse(&vf->priv->lumaParam, args);
+ }
+
+ // check csp:
+ vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
+ if(!vf->priv->outfmt)
+ {
+ uninit(vf);
+ return 0; // no csp match :(
+ }
+
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX){
+ lineNoise= lineNoise_MMX;
+ lineNoiseAvg= lineNoiseAvg_MMX;
+ }
+#endif
+#if HAVE_MMX2
+ if(gCpuCaps.hasMMX2) lineNoise= lineNoise_MMX2;
+// if(gCpuCaps.hasMMX) lineNoiseAvg= lineNoiseAvg_MMX2;
+#endif
+
+ return 1;
+}
+
+const vf_info_t vf_info_noise = {
+ "noise generator",
+ "noise",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_ow.c b/libavfilter/libmpcodecs/vf_ow.c
new file mode 100644
index 0000000000..f7fb02db72
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_ow.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * @todo try to change to int
+ * @todo try lifting based implementation
+ * @todo optimize optimize optimize
+ * @todo hard tresholding
+ * @todo use QP to decide filter strength
+ * @todo wavelet normalization / least squares optimal signal vs. noise thresholds
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "mp_msg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+//===========================================================================//
+static const uint8_t __attribute__((aligned(8))) dither[8][8]={
+{ 0, 48, 12, 60, 3, 51, 15, 63, },
+{ 32, 16, 44, 28, 35, 19, 47, 31, },
+{ 8, 56, 4, 52, 11, 59, 7, 55, },
+{ 40, 24, 36, 20, 43, 27, 39, 23, },
+{ 2, 50, 14, 62, 1, 49, 13, 61, },
+{ 34, 18, 46, 30, 33, 17, 45, 29, },
+{ 10, 58, 6, 54, 9, 57, 5, 53, },
+{ 42, 26, 38, 22, 41, 25, 37, 21, },
+};
+//FIXME the above is duplicated in many filters
+
+struct vf_priv_s {
+ float strength[2];
+ float delta;
+ int mode;
+ int depth;
+ float *plane[16][4];
+ int stride;
+};
+
+#define S 1.41421356237 //sqrt(2)
+
+static const double coeff[2][5]={
+ {
+ 0.6029490182363579 *S,
+ 0.2668641184428723 *S,
+ -0.07822326652898785 *S,
+ -0.01686411844287495 *S,
+ 0.02674875741080976 *S
+ },{
+ 1.115087052456994 /S,
+ -0.5912717631142470 /S,
+ -0.05754352622849957 /S,
+ 0.09127176311424948 /S
+ }
+};
+
+static const double icoeff[2][5]={
+ {
+ 1.115087052456994 /S,
+ 0.5912717631142470 /S,
+ -0.05754352622849957 /S,
+ -0.09127176311424948 /S
+ },{
+ 0.6029490182363579 *S,
+ -0.2668641184428723 *S,
+ -0.07822326652898785 *S,
+ 0.01686411844287495 *S,
+ 0.02674875741080976 *S
+ }
+};
+#undef S
+
+static inline int mirror(int x, int w){
+ while((unsigned)x > (unsigned)w){
+ x=-x;
+ if(x<0) x+= 2*w;
+ }
+ return x;
+}
+
+static inline void decompose(float *dstL, float *dstH, float *src, int stride, int w){
+ int x, i;
+ for(x=0; x<w; x++){
+ double sumL= src[x*stride] * coeff[0][0];
+ double sumH= src[x*stride] * coeff[1][0];
+ for(i=1; i<=4; i++){
+ double s= (src[mirror(x-i, w-1)*stride] + src[mirror(x+i, w-1)*stride]);
+
+ sumL+= coeff[0][i]*s;
+ sumH+= coeff[1][i]*s;
+ }
+ dstL[x*stride]= sumL;
+ dstH[x*stride]= sumH;
+ }
+}
+
+static inline void compose(float *dst, float *srcL, float *srcH, int stride, int w){
+ int x, i;
+ for(x=0; x<w; x++){
+ double sumL= srcL[x*stride] * icoeff[0][0];
+ double sumH= srcH[x*stride] * icoeff[1][0];
+ for(i=1; i<=4; i++){
+ int x0= mirror(x-i, w-1)*stride;
+ int x1= mirror(x+i, w-1)*stride;
+
+ sumL+= icoeff[0][i]*(srcL[x0] + srcL[x1]);
+ sumH+= icoeff[1][i]*(srcH[x0] + srcH[x1]);
+ }
+ dst[x*stride]= (sumL + sumH)*0.5;
+ }
+}
+
+static inline void decompose2D(float *dstL, float *dstH, float *src, int xstride, int ystride, int step, int w, int h){
+ int y, x;
+ for(y=0; y<h; y++)
+ for(x=0; x<step; x++)
+ decompose(dstL + ystride*y + xstride*x, dstH + ystride*y + xstride*x, src + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step);
+}
+
+static inline void compose2D(float *dst, float *srcL, float *srcH, int xstride, int ystride, int step, int w, int h){
+ int y, x;
+ for(y=0; y<h; y++)
+ for(x=0; x<step; x++)
+ compose(dst + ystride*y + xstride*x, srcL + ystride*y + xstride*x, srcH + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step);
+}
+
+static void decompose2D2(float *dst[4], float *src, float *temp[2], int stride, int step, int w, int h){
+ decompose2D(temp[0], temp[1], src , 1, stride, step , w, h);
+ decompose2D( dst[0], dst[1], temp[0], stride, 1, step , h, w);
+ decompose2D( dst[2], dst[3], temp[1], stride, 1, step , h, w);
+}
+
+static void compose2D2(float *dst, float *src[4], float *temp[2], int stride, int step, int w, int h){
+ compose2D(temp[0], src[0], src[1], stride, 1, step , h, w);
+ compose2D(temp[1], src[2], src[3], stride, 1, step , h, w);
+ compose2D(dst , temp[0], temp[1], 1, stride, step , w, h);
+}
+
+static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, int is_luma){
+ int x,y, i, j;
+// double sum=0;
+ double s= p->strength[!is_luma];
+ int depth= p->depth;
+
+ while(1<<depth > width || 1<<depth > height)
+ depth--;
+
+ for(y=0; y<height; y++)
+ for(x=0; x<width; x++)
+ p->plane[0][0][x + y*p->stride]= src[x + y*src_stride];
+
+ for(i=0; i<depth; i++){
+ decompose2D2(p->plane[i+1], p->plane[i][0], p->plane[0]+1,p->stride, 1<<i, width, height);
+ }
+ for(i=0; i<depth; i++){
+ for(j=1; j<4; j++){
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ double v= p->plane[i+1][j][x + y*p->stride];
+ if (v> s) v-=s;
+ else if(v<-s) v+=s;
+ else v =0;
+ p->plane[i+1][j][x + y*p->stride]= v;
+ }
+ }
+ }
+ }
+ for(i=depth-1; i>=0; i--){
+ compose2D2(p->plane[i][0], p->plane[i+1], p->plane[0]+1, p->stride, 1<<i, width, height);
+ }
+
+ for(y=0; y<height; y++)
+ for(x=0; x<width; x++){
+ i= p->plane[0][0][x + y*p->stride] + dither[x&7][y&7]*(1.0/64) + 1.0/128; //yes the rounding is insane but optimal :)
+// double e= i - src[x + y*src_stride];
+// sum += e*e;
+ if((unsigned)i > 255U) i= ~(i>>31);
+ dst[x + y*dst_stride]= i;
+ }
+
+// printf("%f\n", sum/height/width);
+}
+
+static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt){
+ int h= (height+15)&(~15);
+ int i,j;
+
+ vf->priv->stride= (width+15)&(~15);
+ for(j=0; j<4; j++){
+ for(i=0; i<=vf->priv->depth; i++)
+ vf->priv->plane[i][j]= malloc(vf->priv->stride*h*sizeof(vf->priv->plane[0][0][0]));
+ }
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->width,mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+ }else{
+ dmpi=vf->dmpi;
+ }
+
+ filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, 1);
+ filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
+ filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ int i,j;
+ if(!vf->priv) return;
+
+ for(j=0; j<4; j++){
+ for(i=0; i<16; i++){
+ free(vf->priv->plane[i][j]);
+ vf->priv->plane[i][j]= NULL;
+ }
+ }
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt){
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ vf->priv->depth= 8;
+ vf->priv->strength[0]= 1.0;
+ vf->priv->strength[1]= 1.0;
+ vf->priv->delta= 1.0;
+
+ if (args) sscanf(args, "%d:%f:%f:%d:%f", &vf->priv->depth,
+ &vf->priv->strength[0],
+ &vf->priv->strength[1],
+ &vf->priv->mode,
+ &vf->priv->delta);
+
+ return 1;
+}
+
+const vf_info_t vf_info_ow = {
+ "overcomplete wavelet denoiser",
+ "ow",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_palette.c b/libavfilter/libmpcodecs/vf_palette.c
new file mode 100644
index 0000000000..45fc41ba45
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_palette.c
@@ -0,0 +1,235 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "mpbswap.h"
+
+#include "libswscale/swscale.h"
+
+//===========================================================================//
+
+// commented out 16 and 15 bit output support, because the conversion
+// routines are incorrrect. they assume the palette to be of the same
+// depth as the output, which is incorrect. --Joey
+
+static const unsigned int bgr_list[]={
+ IMGFMT_BGR32,
+ IMGFMT_BGR24,
+// IMGFMT_BGR16,
+// IMGFMT_BGR15,
+ 0
+};
+static const unsigned int rgb_list[]={
+ IMGFMT_RGB32,
+ IMGFMT_RGB24,
+// IMGFMT_RGB16,
+// IMGFMT_RGB15,
+ 0
+};
+
+/**
+ * Palette is assumed to contain BGR16, see rgb32to16 to convert the palette.
+ */
+static void palette8torgb16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for (i=0; i<num_pixels; i++)
+ ((uint16_t *)dst)[i] = ((const uint16_t *)palette)[src[i]];
+}
+
+static void palette8tobgr16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for (i=0; i<num_pixels; i++)
+ ((uint16_t *)dst)[i] = bswap_16(((const uint16_t *)palette)[src[i]]);
+}
+
+static unsigned int gray_pal[256];
+
+static unsigned int find_best(struct vf_instance *vf, unsigned int fmt){
+ unsigned int best=0;
+ int ret;
+ const unsigned int* p;
+ if(fmt==IMGFMT_BGR8) p=bgr_list;
+ else if(fmt==IMGFMT_RGB8) p=rgb_list;
+ else return 0;
+ while(*p){
+ ret=vf->next->query_format(vf->next,*p);
+ mp_msg(MSGT_VFILTER,MSGL_DBG2,"[%s] query(%s) -> %d\n",vf->info->name,vo_format_name(*p),ret&3);
+ if(ret&VFCAP_CSP_SUPPORTED_BY_HW){ best=*p; break;} // no conversion -> bingo!
+ if(ret&VFCAP_CSP_SUPPORTED && !best) best=*p; // best with conversion
+ ++p;
+ }
+ return best;
+}
+
+//===========================================================================//
+
+struct vf_priv_s {
+ unsigned int fmt;
+ int pal_msg;
+};
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ if (!vf->priv->fmt)
+ vf->priv->fmt=find_best(vf,outfmt);
+ if(!vf->priv->fmt){
+ // no matching fmt, so force one...
+ if(outfmt==IMGFMT_RGB8) vf->priv->fmt=IMGFMT_RGB32;
+ else if(outfmt==IMGFMT_BGR8) vf->priv->fmt=IMGFMT_BGR32;
+ else return 0;
+ }
+ return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ uint8_t *old_palette = mpi->planes[1];
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,vf->priv->fmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w, mpi->h);
+
+ if (!mpi->planes[1])
+ {
+ if(!vf->priv->pal_msg){
+ mp_msg(MSGT_VFILTER,MSGL_V,"[%s] no palette given, assuming builtin grayscale one\n",vf->info->name);
+ vf->priv->pal_msg=1;
+ }
+ mpi->planes[1] = (unsigned char*)gray_pal;
+ }
+
+ if(mpi->w==mpi->stride[0] && dmpi->w*(dmpi->bpp>>3)==dmpi->stride[0]){
+ // no stride conversion needed
+ switch(IMGFMT_RGB_DEPTH(dmpi->imgfmt)){
+ case 15:
+ case 16:
+ if (IMGFMT_IS_BGR(dmpi->imgfmt))
+ palette8tobgr16(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
+ else
+ palette8torgb16(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
+ break;
+ case 24:
+ if (IMGFMT_IS_BGR(dmpi->imgfmt))
+ sws_convertPalette8ToPacked24(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
+ else
+ sws_convertPalette8ToPacked24(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
+ break;
+ case 32:
+ if (IMGFMT_IS_BGR(dmpi->imgfmt))
+ sws_convertPalette8ToPacked32(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
+ else
+ sws_convertPalette8ToPacked32(mpi->planes[0],dmpi->planes[0],mpi->h*mpi->w,mpi->planes[1]);
+ break;
+ }
+ } else {
+ int y;
+ for(y=0;y<mpi->h;y++){
+ unsigned char* src=mpi->planes[0]+y*mpi->stride[0];
+ unsigned char* dst=dmpi->planes[0]+y*dmpi->stride[0];
+ switch(IMGFMT_RGB_DEPTH(dmpi->imgfmt)){
+ case 15:
+ case 16:
+ if (IMGFMT_IS_BGR(dmpi->imgfmt))
+ palette8tobgr16(src,dst,mpi->w,mpi->planes[1]);
+ else
+ palette8torgb16(src,dst,mpi->w,mpi->planes[1]);
+ break;
+ case 24:
+ if (IMGFMT_IS_BGR(dmpi->imgfmt))
+ sws_convertPalette8ToPacked24(src,dst,mpi->w,mpi->planes[1]);
+ else
+ sws_convertPalette8ToPacked24(src,dst,mpi->w,mpi->planes[1]);
+ break;
+ case 32:
+ if (IMGFMT_IS_BGR(dmpi->imgfmt))
+ sws_convertPalette8ToPacked32(src,dst,mpi->w,mpi->planes[1]);
+ else
+ sws_convertPalette8ToPacked32(src,dst,mpi->w,mpi->planes[1]);
+ break;
+ }
+ }
+ }
+ mpi->planes[1] = old_palette;
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ int best=find_best(vf,fmt);
+ if(!best) return 0; // no match
+ return vf->next->query_format(vf->next,best);
+}
+
+static void uninit(vf_instance_t *vf) {
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ unsigned int i;
+ vf->config=config;
+ vf->uninit=uninit;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+ for(i=0;i<256;i++) gray_pal[i]=0x01010101*i;
+ if (args)
+ {
+ if (!strcasecmp(args,"rgb15")) vf->priv->fmt=IMGFMT_RGB15; else
+ if (!strcasecmp(args,"rgb16")) vf->priv->fmt=IMGFMT_RGB16; else
+ if (!strcasecmp(args,"rgb24")) vf->priv->fmt=IMGFMT_RGB24; else
+ if (!strcasecmp(args,"rgb32")) vf->priv->fmt=IMGFMT_RGB32; else
+ if (!strcasecmp(args,"bgr15")) vf->priv->fmt=IMGFMT_BGR15; else
+ if (!strcasecmp(args,"bgr16")) vf->priv->fmt=IMGFMT_BGR16; else
+ if (!strcasecmp(args,"bgr24")) vf->priv->fmt=IMGFMT_BGR24; else
+ if (!strcasecmp(args,"bgr32")) vf->priv->fmt=IMGFMT_BGR32; else
+ {
+ mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_UnknownFormatName, args);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+const vf_info_t vf_info_palette = {
+ "8bpp indexed (using palette) -> BGR 15/16/24/32 conversion",
+ "palette",
+ "A'rpi & Alex",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_perspective.c b/libavfilter/libmpcodecs/vf_perspective.c
new file mode 100644
index 0000000000..40a7c7a073
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_perspective.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <math.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#define SUB_PIXEL_BITS 8
+#define SUB_PIXELS (1<<SUB_PIXEL_BITS)
+#define COEFF_BITS 11
+
+//===========================================================================//
+
+struct vf_priv_s {
+ double ref[4][2];
+ int32_t coeff[1<<SUB_PIXEL_BITS][4];
+ int32_t (*pv)[2];
+ int pvStride;
+ int cubic;
+};
+
+
+/***************************************************************************/
+
+static void initPv(struct vf_priv_s *priv, int W, int H){
+ double a,b,c,d,e,f,g,h,D;
+ double (*ref)[2]= priv->ref;
+ int x,y;
+
+ g= ( (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[2][1] - ref[3][1])
+ - (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[2][0] - ref[3][0]))*H;
+ h= ( (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[1][0] - ref[3][0])
+ - (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[1][1] - ref[3][1]))*W;
+ D= (ref[1][0] - ref[3][0])*(ref[2][1] - ref[3][1])
+ - (ref[2][0] - ref[3][0])*(ref[1][1] - ref[3][1]);
+
+ a= D*(ref[1][0] - ref[0][0])*H + g*ref[1][0];
+ b= D*(ref[2][0] - ref[0][0])*W + h*ref[2][0];
+ c= D*ref[0][0]*W*H;
+ d= D*(ref[1][1] - ref[0][1])*H + g*ref[1][1];
+ e= D*(ref[2][1] - ref[0][1])*W + h*ref[2][1];
+ f= D*ref[0][1]*W*H;
+
+ for(y=0; y<H; y++){
+ for(x=0; x<W; x++){
+ int u, v;
+
+ u= (int)floor( SUB_PIXELS*(a*x + b*y + c)/(g*x + h*y + D*W*H) + 0.5);
+ v= (int)floor( SUB_PIXELS*(d*x + e*y + f)/(g*x + h*y + D*W*H) + 0.5);
+
+ priv->pv[x + y*W][0]= u;
+ priv->pv[x + y*W][1]= v;
+ }
+ }
+}
+
+static double getCoeff(double d){
+ double A= -0.60;
+ double coeff;
+
+ d= fabs(d);
+
+ // Equation is from VirtualDub
+ if(d<1.0)
+ coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d);
+ else if(d<2.0)
+ coeff = (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d);
+ else
+ coeff=0.0;
+
+ return coeff;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ int i, j;
+
+ vf->priv->pvStride= width;
+ vf->priv->pv= (void*)memalign(8, width*height*2*sizeof(int32_t));
+ initPv(vf->priv, width, height);
+
+ for(i=0; i<SUB_PIXELS; i++){
+ double d= i/(double)SUB_PIXELS;
+ double temp[4];
+ double sum=0;
+
+ for(j=0; j<4; j++)
+ temp[j]= getCoeff(j - d - 1);
+
+ for(j=0; j<4; j++)
+ sum+= temp[j];
+
+ for(j=0; j<4; j++)
+ vf->priv->coeff[i][j]= (int)floor((1<<COEFF_BITS)*temp[j]/sum + 0.5);
+ }
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ free(vf->priv->pv);
+ vf->priv->pv= NULL;
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+static inline void resampleCubic(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, struct vf_priv_s *privParam, int xShift, int yShift){
+ int x, y;
+ struct vf_priv_s priv= *privParam;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int u, v, subU, subV, sum, sx, sy;
+
+ sx= x << xShift;
+ sy= y << yShift;
+ u= priv.pv[sx + sy*priv.pvStride][0]>>xShift;
+ v= priv.pv[sx + sy*priv.pvStride][1]>>yShift;
+ subU= u & (SUB_PIXELS-1);
+ subV= v & (SUB_PIXELS-1);
+ u >>= SUB_PIXEL_BITS;
+ v >>= SUB_PIXEL_BITS;
+
+ if(u>0 && v>0 && u<w-2 && v<h-2){
+ const int index= u + v*srcStride;
+ const int a= priv.coeff[subU][0];
+ const int b= priv.coeff[subU][1];
+ const int c= priv.coeff[subU][2];
+ const int d= priv.coeff[subU][3];
+
+ sum=
+ priv.coeff[subV][0]*( a*src[index - 1 - srcStride] + b*src[index - 0 - srcStride]
+ + c*src[index + 1 - srcStride] + d*src[index + 2 - srcStride])
+ +priv.coeff[subV][1]*( a*src[index - 1 ] + b*src[index - 0 ]
+ + c*src[index + 1 ] + d*src[index + 2 ])
+ +priv.coeff[subV][2]*( a*src[index - 1 + srcStride] + b*src[index - 0 + srcStride]
+ + c*src[index + 1 + srcStride] + d*src[index + 2 + srcStride])
+ +priv.coeff[subV][3]*( a*src[index - 1+2*srcStride] + b*src[index - 0+2*srcStride]
+ + c*src[index + 1+2*srcStride] + d*src[index + 2+2*srcStride]);
+ }else{
+ int dx, dy;
+ sum=0;
+
+ for(dy=0; dy<4; dy++){
+ int iy= v + dy - 1;
+ if (iy< 0) iy=0;
+ else if(iy>=h) iy=h-1;
+ for(dx=0; dx<4; dx++){
+ int ix= u + dx - 1;
+ if (ix< 0) ix=0;
+ else if(ix>=w) ix=w-1;
+
+ sum+= priv.coeff[subU][dx]*priv.coeff[subV][dy]
+ *src[ ix + iy*srcStride];
+ }
+ }
+ }
+ sum= (sum + (1<<(COEFF_BITS*2-1)) ) >> (COEFF_BITS*2);
+ if(sum&~255){
+ if(sum<0) sum=0;
+ else sum=255;
+ }
+ dst[ x + y*dstStride]= sum;
+ }
+ }
+}
+
+static inline void resampleLinear(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride,
+ struct vf_priv_s *privParam, int xShift, int yShift){
+ int x, y;
+ struct vf_priv_s priv= *privParam;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int u, v, subU, subV, sum, sx, sy, index, subUI, subVI;
+
+ sx= x << xShift;
+ sy= y << yShift;
+ u= priv.pv[sx + sy*priv.pvStride][0]>>xShift;
+ v= priv.pv[sx + sy*priv.pvStride][1]>>yShift;
+ subU= u & (SUB_PIXELS-1);
+ subV= v & (SUB_PIXELS-1);
+ u >>= SUB_PIXEL_BITS;
+ v >>= SUB_PIXEL_BITS;
+ index= u + v*srcStride;
+ subUI= SUB_PIXELS - subU;
+ subVI= SUB_PIXELS - subV;
+
+ if((unsigned)u < (unsigned)(w - 1)){
+ if((unsigned)v < (unsigned)(h - 1)){
+ sum= subVI*(subUI*src[index ] + subU*src[index +1])
+ +subV *(subUI*src[index+srcStride] + subU*src[index+srcStride+1]);
+ sum= (sum + (1<<(SUB_PIXEL_BITS*2-1)) ) >> (SUB_PIXEL_BITS*2);
+ }else{
+ if(v<0) v= 0;
+ else v= h-1;
+ index= u + v*srcStride;
+ sum= subUI*src[index] + subU*src[index+1];
+ sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS;
+ }
+ }else{
+ if((unsigned)v < (unsigned)(h - 1)){
+ if(u<0) u= 0;
+ else u= w-1;
+ index= u + v*srcStride;
+ sum= subVI*src[index] + subV*src[index+srcStride];
+ sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS;
+ }else{
+ if(u<0) u= 0;
+ else u= w-1;
+ if(v<0) v= 0;
+ else v= h-1;
+ index= u + v*srcStride;
+ sum= src[index];
+ }
+ }
+ if(sum&~255){
+ if(sum<0) sum=0;
+ else sum=255;
+ }
+ dst[ x + y*dstStride]= sum;
+ }
+ }
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+
+ mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+
+ assert(mpi->flags&MP_IMGFLAG_PLANAR);
+
+ if(vf->priv->cubic){
+ resampleCubic(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0],
+ vf->priv, 0, 0);
+ resampleCubic(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1],
+ vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
+ resampleCubic(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2],
+ vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
+ }else{
+ resampleLinear(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0],
+ vf->priv, 0, 0);
+ resampleLinear(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1],
+ vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
+ resampleLinear(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2],
+ vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ int e;
+
+ vf->config=config;
+ vf->put_image=put_image;
+// vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if(args==NULL) return 0;
+
+ e=sscanf(args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf:%d",
+ &vf->priv->ref[0][0], &vf->priv->ref[0][1],
+ &vf->priv->ref[1][0], &vf->priv->ref[1][1],
+ &vf->priv->ref[2][0], &vf->priv->ref[2][1],
+ &vf->priv->ref[3][0], &vf->priv->ref[3][1],
+ &vf->priv->cubic
+ );
+
+ if(e!=9)
+ return 0;
+
+ return 1;
+}
+
+const vf_info_t vf_info_perspective = {
+ "perspective correcture",
+ "perspective",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_phase.c b/libavfilter/libmpcodecs/vf_phase.c
new file mode 100644
index 0000000000..7dd642ebc0
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_phase.c
@@ -0,0 +1,301 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+enum mode { PROGRESSIVE, TOP_FIRST, BOTTOM_FIRST,
+ TOP_FIRST_ANALYZE, BOTTOM_FIRST_ANALYZE,
+ ANALYZE, FULL_ANALYZE, AUTO, AUTO_ANALYZE };
+
+#define fixed_mode(p) ((p)<=BOTTOM_FIRST)
+
+struct vf_priv_s
+ {
+ enum mode mode;
+ int verbose;
+ unsigned char *buf[3];
+ };
+
+/*
+ * Copy fields from either current or buffered previous frame to the
+ * output and store the current frame unmodified to the buffer.
+ */
+
+static void do_plane(unsigned char *to, unsigned char *from,
+ int w, int h, int ts, int fs,
+ unsigned char **bufp, enum mode mode)
+ {
+ unsigned char *buf, *end;
+ int top;
+
+ if(!*bufp)
+ {
+ mode=PROGRESSIVE;
+ if(!(*bufp=malloc(h*w))) return;
+ }
+
+ for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1)
+ {
+ fast_memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
+ fast_memcpy(buf, from, w);
+ }
+ }
+
+/*
+ * This macro interpolates the value of both fields at a point halfway
+ * between lines and takes the squared difference. In field resolution
+ * the point is a quarter pixel below a line in one field and a quarter
+ * pixel above a line in other.
+ *
+ * (the result is actually multiplied by 25)
+ */
+
+#define diff(a, as, b, bs) (t=((*a-b[bs])<<2)+a[as<<1]-b[-bs], t*t)
+
+/*
+ * Find which field combination has the smallest average squared difference
+ * between the fields.
+ */
+
+static enum mode analyze_plane(unsigned char *old, unsigned char *new,
+ int w, int h, int os, int ns, enum mode mode,
+ int verbose, int fields)
+ {
+ double bdiff, pdiff, tdiff, scale;
+ int bdif, tdif, pdif;
+ int top, t;
+ unsigned char *end, *rend;
+
+ if(mode==AUTO)
+ mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
+ TOP_FIRST:BOTTOM_FIRST:PROGRESSIVE;
+ else if(mode==AUTO_ANALYZE)
+ mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
+ TOP_FIRST_ANALYZE:BOTTOM_FIRST_ANALYZE:FULL_ANALYZE;
+
+ if(fixed_mode(mode))
+ bdiff=pdiff=tdiff=65536.0;
+ else
+ {
+ bdiff=pdiff=tdiff=0.0;
+
+ for(end=new+(h-2)*ns, new+=ns, old+=os, top=0;
+ new<end; new+=ns-w, old+=os-w, top^=1)
+ {
+ pdif=tdif=bdif=0;
+
+ switch(mode)
+ {
+ case TOP_FIRST_ANALYZE:
+ if(top)
+ for(rend=new+w; new<rend; new++, old++)
+ pdif+=diff(new, ns, new, ns),
+ tdif+=diff(new, ns, old, os);
+ else
+ for(rend=new+w; new<rend; new++, old++)
+ pdif+=diff(new, ns, new, ns),
+ tdif+=diff(old, os, new, ns);
+ break;
+
+ case BOTTOM_FIRST_ANALYZE:
+ if(top)
+ for(rend=new+w; new<rend; new++, old++)
+ pdif+=diff(new, ns, new, ns),
+ bdif+=diff(old, os, new, ns);
+ else
+ for(rend=new+w; new<rend; new++, old++)
+ pdif+=diff(new, ns, new, ns),
+ bdif+=diff(new, ns, old, os);
+ break;
+
+ case ANALYZE:
+ if(top)
+ for(rend=new+w; new<rend; new++, old++)
+ tdif+=diff(new, ns, old, os),
+ bdif+=diff(old, os, new, ns);
+ else
+ for(rend=new+w; new<rend; new++, old++)
+ bdif+=diff(new, ns, old, os),
+ tdif+=diff(old, os, new, ns);
+ break;
+
+ default: /* FULL_ANALYZE */
+ if(top)
+ for(rend=new+w; new<rend; new++, old++)
+ pdif+=diff(new, ns, new, ns),
+ tdif+=diff(new, ns, old, os),
+ bdif+=diff(old, os, new, ns);
+ else
+ for(rend=new+w; new<rend; new++, old++)
+ pdif+=diff(new, ns, new, ns),
+ bdif+=diff(new, ns, old, os),
+ tdif+=diff(old, os, new, ns);
+ }
+
+ pdiff+=(double)pdif;
+ tdiff+=(double)tdif;
+ bdiff+=(double)bdif;
+ }
+
+ scale=1.0/(w*(h-3))/25.0;
+ pdiff*=scale;
+ tdiff*=scale;
+ bdiff*=scale;
+
+ if(mode==TOP_FIRST_ANALYZE)
+ bdiff=65536.0;
+ else if(mode==BOTTOM_FIRST_ANALYZE)
+ tdiff=65536.0;
+ else if(mode==ANALYZE)
+ pdiff=65536.0;
+
+ if(bdiff<pdiff && bdiff<tdiff)
+ mode=BOTTOM_FIRST;
+ else if(tdiff<pdiff && tdiff<bdiff)
+ mode=TOP_FIRST;
+ else
+ mode=PROGRESSIVE;
+ }
+
+ if( mp_msg_test(MSGT_VFILTER,MSGL_V) )
+ {
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
+ if(tdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", tdiff);
+ if(bdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", bdiff);
+ if(pdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", pdiff);
+ mp_msg(MSGT_VFILTER, MSGL_INFO," \n");
+ }
+
+ return mode;
+ }
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+ {
+ mp_image_t *dmpi;
+ int w;
+ enum mode mode;
+
+ if(!(dmpi=vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w, mpi->h)))
+ return 0;
+
+ w=dmpi->w;
+ if(!(dmpi->flags&MP_IMGFLAG_PLANAR))
+ w*=dmpi->bpp/8;
+
+ mode=vf->priv->mode;
+
+ if(!vf->priv->buf[0])
+ mode=PROGRESSIVE;
+ else
+ mode=analyze_plane(vf->priv->buf[0], mpi->planes[0],
+ w, dmpi->h, w, mpi->stride[0], mode,
+ vf->priv->verbose, mpi->fields);
+
+ do_plane(dmpi->planes[0], mpi->planes[0],
+ w, dmpi->h,
+ dmpi->stride[0], mpi->stride[0],
+ &vf->priv->buf[0], mode);
+
+ if(dmpi->flags&MP_IMGFLAG_PLANAR)
+ {
+ do_plane(dmpi->planes[1], mpi->planes[1],
+ dmpi->chroma_width, dmpi->chroma_height,
+ dmpi->stride[1], mpi->stride[1],
+ &vf->priv->buf[1], mode);
+ do_plane(dmpi->planes[2], mpi->planes[2],
+ dmpi->chroma_width, dmpi->chroma_height,
+ dmpi->stride[2], mpi->stride[2],
+ &vf->priv->buf[2], mode);
+ }
+
+ return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ }
+
+static void uninit(struct vf_instance *vf)
+ {
+ free(vf->priv->buf[0]);
+ free(vf->priv->buf[1]);
+ free(vf->priv->buf[2]);
+ free(vf->priv);
+ }
+
+static int vf_open(vf_instance_t *vf, char *args)
+ {
+ vf->put_image = put_image;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+
+ if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s))))
+ {
+ uninit(vf);
+ return 0;
+ }
+
+ vf->priv->mode=AUTO_ANALYZE;
+ vf->priv->verbose=0;
+
+ while(args && *args)
+ {
+ switch(*args)
+ {
+ case 't': vf->priv->mode=TOP_FIRST; break;
+ case 'a': vf->priv->mode=AUTO; break;
+ case 'b': vf->priv->mode=BOTTOM_FIRST; break;
+ case 'u': vf->priv->mode=ANALYZE; break;
+ case 'T': vf->priv->mode=TOP_FIRST_ANALYZE; break;
+ case 'A': vf->priv->mode=AUTO_ANALYZE; break;
+ case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break;
+ case 'U': vf->priv->mode=FULL_ANALYZE; break;
+ case 'p': vf->priv->mode=PROGRESSIVE; break;
+ case 'v': vf->priv->verbose=1; break;
+ case ':': break;
+
+ default:
+ uninit(vf);
+ return 0; /* bad args */
+ }
+
+ if( (args=strchr(args, ':')) ) args++;
+ }
+
+ return 1;
+ }
+
+const vf_info_t vf_info_phase =
+ {
+ "phase shift fields",
+ "phase",
+ "Ville Saari",
+ "",
+ vf_open,
+ NULL
+ };
diff --git a/libavfilter/libmpcodecs/vf_pp7.c b/libavfilter/libmpcodecs/vf_pp7.c
new file mode 100644
index 0000000000..0f28de86c8
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_pp7.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+
+#define XMIN(a,b) ((a) < (b) ? (a) : (b))
+#define XMAX(a,b) ((a) > (b) ? (a) : (b))
+
+typedef short DCTELEM;
+
+//===========================================================================//
+static const uint8_t __attribute__((aligned(8))) dither[8][8]={
+{ 0, 48, 12, 60, 3, 51, 15, 63, },
+{ 32, 16, 44, 28, 35, 19, 47, 31, },
+{ 8, 56, 4, 52, 11, 59, 7, 55, },
+{ 40, 24, 36, 20, 43, 27, 39, 23, },
+{ 2, 50, 14, 62, 1, 49, 13, 61, },
+{ 34, 18, 46, 30, 33, 17, 45, 29, },
+{ 10, 58, 6, 54, 9, 57, 5, 53, },
+{ 42, 26, 38, 22, 41, 25, 37, 21, },
+};
+
+struct vf_priv_s {
+ int qp;
+ int mode;
+ int mpeg2;
+ int temp_stride;
+ uint8_t *src;
+};
+#if 0
+static inline void dct7_c(DCTELEM *dst, int s0, int s1, int s2, int s3, int step){
+ int s, d;
+ int dst2[64];
+//#define S0 (1024/0.37796447300922719759)
+#define C0 ((int)(1024*0.37796447300922719759+0.5)) //sqrt(1/7)
+#define C1 ((int)(1024*0.53452248382484879308/6+0.5)) //sqrt(2/7)/6
+
+#define C2 ((int)(1024*0.45221175985034745004/2+0.5))
+#define C3 ((int)(1024*0.36264567479870879474/2+0.5))
+
+//0.1962505182412941918 0.0149276808419397944-0.2111781990832339584
+#define C4 ((int)(1024*0.1962505182412941918+0.5))
+#define C5 ((int)(1024*0.0149276808419397944+0.5))
+//#define C6 ((int)(1024*0.2111781990832339584+0.5))
+#if 0
+ s= s0 + s1 + s2;
+ dst[0*step] = ((s + s3)*C0 + 512) >> 10;
+ s= (s - 6*s3)*C1 + 512;
+ d= (s0-s2)*C4 + (s1-s2)*C5;
+ dst[1*step] = (s + 2*d)>>10;
+ s -= d;
+ d= (s1-s0)*C2 + (s1-s2)*C3;
+ dst[2*step] = (s + d)>>10;
+ dst[3*step] = (s - d)>>10;
+#elif 1
+ s = s3+s3;
+ s3= s-s0;
+ s0= s+s0;
+ s = s2+s1;
+ s2= s2-s1;
+ dst[0*step]= s0 + s;
+ dst[2*step]= s0 - s;
+ dst[1*step]= 2*s3 + s2;
+ dst[3*step]= s3 - 2*s2;
+#else
+ int i,j,n=7;
+ for(i=0; i<7; i+=2){
+ dst2[i*step/2]= 0;
+ for(j=0; j<4; j++)
+ dst2[i*step/2] += src[j*step] * cos(i*M_PI/n*(j+0.5)) * sqrt((i?2.0:1.0)/n);
+ if(fabs(dst2[i*step/2] - dst[i*step/2]) > 20)
+ printf("%d %d %d (%d %d %d %d) -> (%d %d %d %d)\n", i,dst2[i*step/2], dst[i*step/2],src[0*step], src[1*step], src[2*step], src[3*step], dst[0*step], dst[1*step],dst[2*step],dst[3*step]);
+ }
+#endif
+}
+#endif
+
+static inline void dctA_c(DCTELEM *dst, uint8_t *src, int stride){
+ int i;
+
+ for(i=0; i<4; i++){
+ int s0= src[0*stride] + src[6*stride];
+ int s1= src[1*stride] + src[5*stride];
+ int s2= src[2*stride] + src[4*stride];
+ int s3= src[3*stride];
+ int s= s3+s3;
+ s3= s-s0;
+ s0= s+s0;
+ s = s2+s1;
+ s2= s2-s1;
+ dst[0]= s0 + s;
+ dst[2]= s0 - s;
+ dst[1]= 2*s3 + s2;
+ dst[3]= s3 - 2*s2;
+ src++;
+ dst+=4;
+ }
+}
+
+static void dctB_c(DCTELEM *dst, DCTELEM *src){
+ int i;
+
+ for(i=0; i<4; i++){
+ int s0= src[0*4] + src[6*4];
+ int s1= src[1*4] + src[5*4];
+ int s2= src[2*4] + src[4*4];
+ int s3= src[3*4];
+ int s= s3+s3;
+ s3= s-s0;
+ s0= s+s0;
+ s = s2+s1;
+ s2= s2-s1;
+ dst[0*4]= s0 + s;
+ dst[2*4]= s0 - s;
+ dst[1*4]= 2*s3 + s2;
+ dst[3*4]= s3 - 2*s2;
+ src++;
+ dst++;
+ }
+}
+
+#if HAVE_MMX
+static void dctB_mmx(DCTELEM *dst, DCTELEM *src){
+ __asm__ volatile (
+ "movq (%0), %%mm0 \n\t"
+ "movq 1*4*2(%0), %%mm1 \n\t"
+ "paddw 6*4*2(%0), %%mm0 \n\t"
+ "paddw 5*4*2(%0), %%mm1 \n\t"
+ "movq 2*4*2(%0), %%mm2 \n\t"
+ "movq 3*4*2(%0), %%mm3 \n\t"
+ "paddw 4*4*2(%0), %%mm2 \n\t"
+ "paddw %%mm3, %%mm3 \n\t" //s
+ "movq %%mm3, %%mm4 \n\t" //s
+ "psubw %%mm0, %%mm3 \n\t" //s-s0
+ "paddw %%mm0, %%mm4 \n\t" //s+s0
+ "movq %%mm2, %%mm0 \n\t" //s2
+ "psubw %%mm1, %%mm2 \n\t" //s2-s1
+ "paddw %%mm1, %%mm0 \n\t" //s2+s1
+ "movq %%mm4, %%mm1 \n\t" //s0'
+ "psubw %%mm0, %%mm4 \n\t" //s0'-s'
+ "paddw %%mm0, %%mm1 \n\t" //s0'+s'
+ "movq %%mm3, %%mm0 \n\t" //s3'
+ "psubw %%mm2, %%mm3 \n\t"
+ "psubw %%mm2, %%mm3 \n\t"
+ "paddw %%mm0, %%mm2 \n\t"
+ "paddw %%mm0, %%mm2 \n\t"
+ "movq %%mm1, (%1) \n\t"
+ "movq %%mm4, 2*4*2(%1) \n\t"
+ "movq %%mm2, 1*4*2(%1) \n\t"
+ "movq %%mm3, 3*4*2(%1) \n\t"
+ :: "r" (src), "r"(dst)
+ );
+}
+#endif
+
+static void (*dctB)(DCTELEM *dst, DCTELEM *src)= dctB_c;
+
+#define N0 4
+#define N1 5
+#define N2 10
+#define SN0 2
+#define SN1 2.2360679775
+#define SN2 3.16227766017
+#define N (1<<16)
+
+static const int factor[16]={
+ N/(N0*N0), N/(N0*N1), N/(N0*N0),N/(N0*N2),
+ N/(N1*N0), N/(N1*N1), N/(N1*N0),N/(N1*N2),
+ N/(N0*N0), N/(N0*N1), N/(N0*N0),N/(N0*N2),
+ N/(N2*N0), N/(N2*N1), N/(N2*N0),N/(N2*N2),
+};
+
+static const int thres[16]={
+ N/(SN0*SN0), N/(SN0*SN2), N/(SN0*SN0),N/(SN0*SN2),
+ N/(SN2*SN0), N/(SN2*SN2), N/(SN2*SN0),N/(SN2*SN2),
+ N/(SN0*SN0), N/(SN0*SN2), N/(SN0*SN0),N/(SN0*SN2),
+ N/(SN2*SN0), N/(SN2*SN2), N/(SN2*SN0),N/(SN2*SN2),
+};
+
+static int thres2[99][16];
+
+static void init_thres2(void){
+ int qp, i;
+ int bias= 0; //FIXME
+
+ for(qp=0; qp<99; qp++){
+ for(i=0; i<16; i++){
+ thres2[qp][i]= ((i&1)?SN2:SN0) * ((i&4)?SN2:SN0) * XMAX(1,qp) * (1<<2) - 1 - bias;
+ }
+ }
+}
+
+static int hardthresh_c(DCTELEM *src, int qp){
+ int i;
+ int a;
+
+ a= src[0] * factor[0];
+ for(i=1; i<16; i++){
+ unsigned int threshold1= thres2[qp][i];
+ unsigned int threshold2= (threshold1<<1);
+ int level= src[i];
+ if(((unsigned)(level+threshold1))>threshold2){
+ a += level * factor[i];
+ }
+ }
+ return (a + (1<<11))>>12;
+}
+
+static int mediumthresh_c(DCTELEM *src, int qp){
+ int i;
+ int a;
+
+ a= src[0] * factor[0];
+ for(i=1; i<16; i++){
+ unsigned int threshold1= thres2[qp][i];
+ unsigned int threshold2= (threshold1<<1);
+ int level= src[i];
+ if(((unsigned)(level+threshold1))>threshold2){
+ if(((unsigned)(level+2*threshold1))>2*threshold2){
+ a += level * factor[i];
+ }else{
+ if(level>0) a+= 2*(level - (int)threshold1)*factor[i];
+ else a+= 2*(level + (int)threshold1)*factor[i];
+ }
+ }
+ }
+ return (a + (1<<11))>>12;
+}
+
+static int softthresh_c(DCTELEM *src, int qp){
+ int i;
+ int a;
+
+ a= src[0] * factor[0];
+ for(i=1; i<16; i++){
+ unsigned int threshold1= thres2[qp][i];
+ unsigned int threshold2= (threshold1<<1);
+ int level= src[i];
+ if(((unsigned)(level+threshold1))>threshold2){
+ if(level>0) a+= (level - (int)threshold1)*factor[i];
+ else a+= (level + (int)threshold1)*factor[i];
+ }
+ }
+ return (a + (1<<11))>>12;
+}
+
+static int (*requantize)(DCTELEM *src, int qp)= hardthresh_c;
+
+static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, uint8_t *qp_store, int qp_stride, int is_luma){
+ int x, y;
+ const int stride= is_luma ? p->temp_stride : ((width+16+15)&(~15));
+ uint8_t *p_src= p->src + 8*stride;
+ DCTELEM *block= p->src;
+ DCTELEM *temp= p->src + 32;
+
+ if (!src || !dst) return; // HACK avoid crash for Y8 colourspace
+ for(y=0; y<height; y++){
+ int index= 8 + 8*stride + y*stride;
+ fast_memcpy(p_src + index, src + y*src_stride, width);
+ for(x=0; x<8; x++){
+ p_src[index - x - 1]= p_src[index + x ];
+ p_src[index + width + x ]= p_src[index + width - x - 1];
+ }
+ }
+ for(y=0; y<8; y++){
+ fast_memcpy(p_src + ( 7-y)*stride, p_src + ( y+8)*stride, stride);
+ fast_memcpy(p_src + (height+8+y)*stride, p_src + (height-y+7)*stride, stride);
+ }
+ //FIXME (try edge emu)
+
+ for(y=0; y<height; y++){
+ for(x=-8; x<0; x+=4){
+ const int index= x + y*stride + (8-3)*(1+stride) + 8; //FIXME silly offset
+ uint8_t *src = p_src + index;
+ DCTELEM *tp= temp+4*x;
+
+ dctA_c(tp+4*8, src, stride);
+ }
+ for(x=0; x<width; ){
+ const int qps= 3 + is_luma;
+ int qp;
+ int end= XMIN(x+8, width);
+
+ if(p->qp)
+ qp= p->qp;
+ else{
+ qp= qp_store[ (XMIN(x, width-1)>>qps) + (XMIN(y, height-1)>>qps) * qp_stride];
+ qp=norm_qscale(qp, p->mpeg2);
+ }
+ for(; x<end; x++){
+ const int index= x + y*stride + (8-3)*(1+stride) + 8; //FIXME silly offset
+ uint8_t *src = p_src + index;
+ DCTELEM *tp= temp+4*x;
+ int v;
+
+ if((x&3)==0)
+ dctA_c(tp+4*8, src, stride);
+
+ dctB(block, tp);
+
+ v= requantize(block, qp);
+ v= (v + dither[y&7][x&7])>>6;
+ if((unsigned)v > 255)
+ v= (-v)>>31;
+ dst[x + y*dst_stride]= v;
+ }
+ }
+ }
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ int h= (height+16+15)&(~15);
+
+ vf->priv->temp_stride= (width+16+15)&(~15);
+ vf->priv->src = memalign(8, vf->priv->temp_stride*(h+8)*sizeof(uint8_t));
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(mpi->flags&MP_IMGFLAG_DIRECT){
+ dmpi=vf->dmpi;
+ }else{
+ // no DR, so get a new image! hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->width,mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+ }
+
+ vf->priv->mpeg2= mpi->qscale_type;
+ if(mpi->qscale || vf->priv->qp){
+ filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, mpi->qscale, mpi->qstride, 1);
+ filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, mpi->qscale, mpi->qstride, 0);
+ filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, mpi->qscale, mpi->qstride, 0);
+ }else{
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
+ memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
+ }
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
+#endif
+#if HAVE_MMX2
+ if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
+#endif
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ free(vf->priv->src);
+ vf->priv->src= NULL;
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt){
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+static int control(struct vf_instance *vf, int request, void* data){
+ return vf_next_control(vf,request,data);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->control= control;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if (args) sscanf(args, "%d:%d", &vf->priv->qp, &vf->priv->mode);
+
+ if(vf->priv->qp < 0)
+ vf->priv->qp = 0;
+
+ init_thres2();
+
+ switch(vf->priv->mode){
+ case 0: requantize= hardthresh_c; break;
+ case 1: requantize= softthresh_c; break;
+ default:
+ case 2: requantize= mediumthresh_c; break;
+ }
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX){
+ dctB= dctB_mmx;
+ }
+#endif
+#if 0
+ if(gCpuCaps.hasMMX){
+ switch(vf->priv->mode){
+ case 0: requantize= hardthresh_mmx; break;
+ case 1: requantize= softthresh_mmx; break;
+ }
+ }
+#endif
+
+ return 1;
+}
+
+const vf_info_t vf_info_pp7 = {
+ "postprocess 7",
+ "pp7",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_pullup.c b/libavfilter/libmpcodecs/vf_pullup.c
new file mode 100644
index 0000000000..a1ed978a39
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_pullup.c
@@ -0,0 +1,314 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+#include "pullup.h"
+
+#undef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+struct vf_priv_s {
+ struct pullup_context *ctx;
+ int init;
+ int fakecount;
+ char *qbuf;
+};
+
+static void init_pullup(struct vf_instance *vf, mp_image_t *mpi)
+{
+ struct pullup_context *c = vf->priv->ctx;
+
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ c->format = PULLUP_FMT_Y;
+ c->nplanes = 4;
+ pullup_preinit_context(c);
+ c->bpp[0] = c->bpp[1] = c->bpp[2] = 8;
+ c->w[0] = mpi->w;
+ c->h[0] = mpi->h;
+ c->w[1] = c->w[2] = mpi->chroma_width;
+ c->h[1] = c->h[2] = mpi->chroma_height;
+ c->w[3] = ((mpi->w+15)/16) * ((mpi->h+15)/16);
+ c->h[3] = 2;
+ c->stride[0] = mpi->width;
+ c->stride[1] = c->stride[2] = mpi->chroma_width;
+ c->stride[3] = c->w[3];
+ c->background[1] = c->background[2] = 128;
+ }
+
+ if (gCpuCaps.hasMMX) c->cpu |= PULLUP_CPU_MMX;
+ if (gCpuCaps.hasMMX2) c->cpu |= PULLUP_CPU_MMX2;
+ if (gCpuCaps.has3DNow) c->cpu |= PULLUP_CPU_3DNOW;
+ if (gCpuCaps.has3DNowExt) c->cpu |= PULLUP_CPU_3DNOWEXT;
+ if (gCpuCaps.hasSSE) c->cpu |= PULLUP_CPU_SSE;
+ if (gCpuCaps.hasSSE2) c->cpu |= PULLUP_CPU_SSE2;
+
+ pullup_init_context(c);
+
+ vf->priv->init = 1;
+ vf->priv->qbuf = malloc(c->w[3]);
+}
+
+
+#if 0
+static void get_image(struct vf_instance *vf, mp_image_t *mpi)
+{
+ struct pullup_context *c = vf->priv->ctx;
+ struct pullup_buffer *b;
+
+ if (mpi->type == MP_IMGTYPE_STATIC) return;
+
+ if (!vf->priv->init) init_pullup(vf, mpi);
+
+ b = pullup_get_buffer(c, 2);
+ if (!b) return; /* shouldn't happen... */
+
+ mpi->priv = b;
+
+ mpi->planes[0] = b->planes[0];
+ mpi->planes[1] = b->planes[1];
+ mpi->planes[2] = b->planes[2];
+ mpi->stride[0] = c->stride[0];
+ mpi->stride[1] = c->stride[1];
+ mpi->stride[2] = c->stride[2];
+
+ mpi->flags |= MP_IMGFLAG_DIRECT;
+ mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
+}
+#endif
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ struct pullup_context *c = vf->priv->ctx;
+ struct pullup_buffer *b;
+ struct pullup_frame *f;
+ mp_image_t *dmpi;
+ int ret;
+ int p;
+ int i;
+
+ if (!vf->priv->init) init_pullup(vf, mpi);
+
+ if (mpi->flags & MP_IMGFLAG_DIRECT) {
+ b = mpi->priv;
+ mpi->priv = 0;
+ } else {
+ b = pullup_get_buffer(c, 2);
+ if (!b) {
+ mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n");
+ f = pullup_get_frame(c);
+ pullup_release_frame(f);
+ return 0;
+ }
+ memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h,
+ c->stride[0], mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(b->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ c->stride[1], mpi->stride[1]);
+ memcpy_pic(b->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ c->stride[2], mpi->stride[2]);
+ }
+ }
+ if (mpi->qscale) {
+ fast_memcpy(b->planes[3], mpi->qscale, c->w[3]);
+ fast_memcpy(b->planes[3]+c->w[3], mpi->qscale, c->w[3]);
+ }
+
+ p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 :
+ (mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0);
+ pullup_submit_field(c, b, p);
+ pullup_submit_field(c, b, p^1);
+ if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST)
+ pullup_submit_field(c, b, p);
+
+ pullup_release_buffer(b, 2);
+
+ f = pullup_get_frame(c);
+
+ /* Fake yes for first few frames (buffer depth) to keep from
+ * breaking A/V sync with G1's bad architecture... */
+ if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;
+
+ if (f->length < 2) {
+ pullup_release_frame(f);
+ f = pullup_get_frame(c);
+ if (!f) return 0;
+ if (f->length < 2) {
+ pullup_release_frame(f);
+ if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
+ return 0;
+ f = pullup_get_frame(c);
+ if (!f) return 0;
+ if (f->length < 2) {
+ pullup_release_frame(f);
+ return 0;
+ }
+ }
+ }
+
+#if 0
+ /* Average qscale tables from both frames. */
+ if (mpi->qscale) {
+ for (i=0; i<c->w[3]; i++) {
+ vf->priv->qbuf[i] = (f->ofields[0]->planes[3][i]
+ + f->ofields[1]->planes[3][i+c->w[3]])>>1;
+ }
+ }
+#else
+ /* Take worst of qscale tables from both frames. */
+ if (mpi->qscale) {
+ for (i=0; i<c->w[3]; i++) {
+ vf->priv->qbuf[i] = MAX(f->ofields[0]->planes[3][i], f->ofields[1]->planes[3][i+c->w[3]]);
+ }
+ }
+#endif
+
+ /* If the frame isn't already exportable... */
+ while (!f->buffer) {
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->width, mpi->height);
+ /* FIXME: Is it ok to discard dmpi if it's not direct? */
+ if (!(dmpi->flags & MP_IMGFLAG_DIRECT)) {
+ pullup_pack_frame(c, f);
+ break;
+ }
+ /* Direct render fields into output buffer */
+ my_memcpy_pic(dmpi->planes[0], f->ofields[0]->planes[0],
+ mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
+ my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0],
+ f->ofields[1]->planes[0] + c->stride[0],
+ mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1], f->ofields[0]->planes[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, c->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1],
+ f->ofields[1]->planes[1] + c->stride[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, c->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2], f->ofields[0]->planes[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, c->stride[2]*2);
+ my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2],
+ f->ofields[1]->planes[2] + c->stride[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, c->stride[2]*2);
+ }
+ pullup_release_frame(f);
+ if (mpi->qscale) {
+ dmpi->qscale = vf->priv->qbuf;
+ dmpi->qstride = mpi->qstride;
+ dmpi->qscale_type = mpi->qscale_type;
+ }
+ return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ }
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->width, mpi->height);
+
+ dmpi->planes[0] = f->buffer->planes[0];
+ dmpi->planes[1] = f->buffer->planes[1];
+ dmpi->planes[2] = f->buffer->planes[2];
+
+ dmpi->stride[0] = c->stride[0];
+ dmpi->stride[1] = c->stride[1];
+ dmpi->stride[2] = c->stride[2];
+
+ if (mpi->qscale) {
+ dmpi->qscale = vf->priv->qbuf;
+ dmpi->qstride = mpi->qstride;
+ dmpi->qscale_type = mpi->qscale_type;
+ }
+ ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ pullup_release_frame(f);
+ return ret;
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - support more formats */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ if (height&3) return 0;
+ return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ pullup_free_context(vf->priv->ctx);
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ struct pullup_context *c;
+ //vf->get_image = get_image;
+ vf->put_image = put_image;
+ vf->config = config;
+ vf->query_format = query_format;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ p->ctx = c = pullup_alloc_context();
+ p->fakecount = 1;
+ c->verbose = verbose>0;
+ c->junk_left = c->junk_right = 1;
+ c->junk_top = c->junk_bottom = 4;
+ c->strict_breaks = 0;
+ c->metric_plane = 0;
+ if (args) {
+ sscanf(args, "%d:%d:%d:%d:%d:%d", &c->junk_left, &c->junk_right, &c->junk_top, &c->junk_bottom, &c->strict_breaks, &c->metric_plane);
+ }
+ return 1;
+}
+
+const vf_info_t vf_info_pullup = {
+ "pullup (from field sequence to frames)",
+ "pullup",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_qp.c b/libavfilter/libmpcodecs/vf_qp.c
new file mode 100644
index 0000000000..25cd90de40
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_qp.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+
+#include "libavcodec/avcodec.h"
+#include "libavutil/eval.h"
+
+
+struct vf_priv_s {
+ char eq[200];
+ int8_t *qp;
+ int8_t lut[257];
+ int qp_stride;
+};
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ int h= (height+15)>>4;
+ int i;
+
+ vf->priv->qp_stride= (width+15)>>4;
+ vf->priv->qp= av_malloc(vf->priv->qp_stride*h*sizeof(int8_t));
+
+ for(i=-129; i<128; i++){
+ double const_values[]={
+ M_PI,
+ M_E,
+ i != -129,
+ i,
+ 0
+ };
+ static const char *const_names[]={
+ "PI",
+ "E",
+ "known",
+ "qp",
+ NULL
+ };
+ double temp_val;
+ int res;
+
+ res= av_parse_and_eval_expr(&temp_val, vf->priv->eq, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
+
+ if (res < 0){
+ mp_msg(MSGT_VFILTER, MSGL_ERR, "qp: Error evaluating \"%s\" \n", vf->priv->eq);
+ return 0;
+ }
+ vf->priv->lut[i+129]= lrintf(temp_val);
+ }
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags, mpi->w, mpi->h);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ int x,y;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->w,mpi->h);
+ }
+
+ dmpi= vf->dmpi;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
+ }
+ }
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ dmpi->qscale = vf->priv->qp;
+ dmpi->qstride= vf->priv->qp_stride;
+ if(mpi->qscale){
+ for(y=0; y<((dmpi->h+15)>>4); y++){
+ for(x=0; x<vf->priv->qp_stride; x++){
+ dmpi->qscale[x + dmpi->qstride*y]=
+ vf->priv->lut[ 129 + ((int8_t)mpi->qscale[x + mpi->qstride*y]) ];
+ }
+ }
+ }else{
+ int qp= vf->priv->lut[0];
+ for(y=0; y<((dmpi->h+15)>>4); y++){
+ for(x=0; x<vf->priv->qp_stride; x++){
+ dmpi->qscale[x + dmpi->qstride*y]= qp;
+ }
+ }
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ av_free(vf->priv->qp);
+ vf->priv->qp= NULL;
+
+ av_free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->uninit=uninit;
+ vf->priv=av_malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+// avcodec_init();
+
+ if (args) strncpy(vf->priv->eq, args, 199);
+
+ return 1;
+}
+
+const vf_info_t vf_info_qp = {
+ "QP changer",
+ "qp",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_rectangle.c b/libavfilter/libmpcodecs/vf_rectangle.c
new file mode 100644
index 0000000000..21bc209de4
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_rectangle.c
@@ -0,0 +1,181 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mp_image.h"
+#include "mp_msg.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+#include "libavutil/common.h"
+
+struct vf_priv_s {
+ int x, y, w, h;
+};
+
+static int
+config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ if (vf->priv->w < 0 || width < vf->priv->w)
+ vf->priv->w = width;
+ if (vf->priv->h < 0 || height < vf->priv->h)
+ vf->priv->h = height;
+ if (vf->priv->x < 0)
+ vf->priv->x = (width - vf->priv->w) / 2;
+ if (vf->priv->y < 0)
+ vf->priv->y = (height - vf->priv->h) / 2;
+ if (vf->priv->w + vf->priv->x > width
+ || vf->priv->h + vf->priv->y > height) {
+ mp_msg(MSGT_VFILTER,MSGL_WARN,"rectangle: bad position/width/height - rectangle area is out of the original!\n");
+ return 0;
+ }
+ return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
+}
+
+static int
+control(struct vf_instance *vf, int request, void *data)
+{
+ const int *const tmp = data;
+ switch(request){
+ case VFCTRL_CHANGE_RECTANGLE:
+ switch (tmp[0]){
+ case 0:
+ vf->priv->w += tmp[1];
+ return 1;
+ break;
+ case 1:
+ vf->priv->h += tmp[1];
+ return 1;
+ break;
+ case 2:
+ vf->priv->x += tmp[1];
+ return 1;
+ break;
+ case 3:
+ vf->priv->y += tmp[1];
+ return 1;
+ break;
+ default:
+ mp_msg(MSGT_VFILTER,MSGL_FATAL,"Unknown param %d \n", tmp[0]);
+ return 0;
+ }
+ }
+ return vf_next_control(vf, request, data);
+ return 0;
+}
+static int
+put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){
+ mp_image_t* dmpi;
+ unsigned int bpp = mpi->bpp / 8;
+ int x, y, w, h;
+ dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->w, mpi->h);
+
+ memcpy_pic(dmpi->planes[0],mpi->planes[0],mpi->w*bpp, mpi->h,
+ dmpi->stride[0],mpi->stride[0]);
+ if(mpi->flags&MP_IMGFLAG_PLANAR && mpi->flags&MP_IMGFLAG_YUV){
+ memcpy_pic(dmpi->planes[1],mpi->planes[1],
+ mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift,
+ dmpi->stride[1],mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2],mpi->planes[2],
+ mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift,
+ dmpi->stride[2],mpi->stride[2]);
+ }
+
+ /* Draw the rectangle */
+
+ mp_msg(MSGT_VFILTER,MSGL_INFO, "rectangle: -vf rectangle=%d:%d:%d:%d \n", vf->priv->w, vf->priv->h, vf->priv->x, vf->priv->y);
+
+ x = FFMIN(vf->priv->x, dmpi->width);
+ x = FFMAX(x, 0);
+
+ w = vf->priv->x + vf->priv->w - 1 - x;
+ w = FFMIN(w, dmpi->width - x);
+ w = FFMAX(w, 0);
+
+ y = FFMIN(vf->priv->y, dmpi->height);
+ y = FFMAX(y, 0);
+
+ h = vf->priv->y + vf->priv->h - 1 - y;
+ h = FFMIN(h, dmpi->height - y);
+ h = FFMAX(h, 0);
+
+ if (0 <= vf->priv->y && vf->priv->y <= dmpi->height) {
+ unsigned char *p = dmpi->planes[0] + y * dmpi->stride[0] + x * bpp;
+ unsigned int count = w * bpp;
+ while (count--)
+ p[count] = 0xff - p[count];
+ }
+ if (h != 1 && vf->priv->y + vf->priv->h - 1 <= mpi->height) {
+ unsigned char *p = dmpi->planes[0] + (vf->priv->y + vf->priv->h - 1) * dmpi->stride[0] + x * bpp;
+ unsigned int count = w * bpp;
+ while (count--)
+ p[count] = 0xff - p[count];
+ }
+ if (0 <= vf->priv->x && vf->priv->x <= dmpi->width) {
+ unsigned char *p = dmpi->planes[0] + y * dmpi->stride[0] + x * bpp;
+ unsigned int count = h;
+ while (count--) {
+ unsigned int i = bpp;
+ while (i--)
+ p[i] = 0xff - p[i];
+ p += dmpi->stride[0];
+ }
+ }
+ if (w != 1 && vf->priv->x + vf->priv->w - 1 <= mpi->width) {
+ unsigned char *p = dmpi->planes[0] + y * dmpi->stride[0] + (vf->priv->x + vf->priv->w - 1) * bpp;
+ unsigned int count = h;
+ while (count--) {
+ unsigned int i = bpp;
+ while (i--)
+ p[i] = 0xff - p[i];
+ p += dmpi->stride[0];
+ }
+ }
+ return vf_next_put_image(vf, dmpi, pts);
+}
+
+static int
+vf_open(vf_instance_t *vf, char *args) {
+ vf->config = config;
+ vf->control = control;
+ vf->put_image = put_image;
+ vf->priv = malloc(sizeof(struct vf_priv_s));
+ vf->priv->x = -1;
+ vf->priv->y = -1;
+ vf->priv->w = -1;
+ vf->priv->h = -1;
+ if (args)
+ sscanf(args, "%d:%d:%d:%d",
+ &vf->priv->w, &vf->priv->h, &vf->priv->x, &vf->priv->y);
+ return 1;
+}
+
+const vf_info_t vf_info_rectangle = {
+ "draw rectangle",
+ "rectangle",
+ "Kim Minh Kaplan",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_remove_logo.c b/libavfilter/libmpcodecs/vf_remove_logo.c
new file mode 100644
index 0000000000..5f1265eab3
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_remove_logo.c
@@ -0,0 +1,906 @@
+/*
+ * This filter loads a .pgm mask file showing where a logo is and uses
+ * a blur transform to remove the logo.
+ *
+ * Copyright (C) 2005 Robert Edele <yartrebo@earthlink.net>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * \file vf_remove_logo.c
+ *
+ * \brief Advanced blur-based logo removing filter.
+
+ * Hello and welcome. This code implements a filter to remove annoying TV
+ * logos and other annoying images placed onto a video stream. It works by filling
+ * in the pixels that comprise the logo with neighboring pixels. The transform is
+ * very loosely based on a gaussian blur, but it is different enough to merit its
+ * own paragraph later on. It is a major improvement on the old delogo filter as
+ * it both uses a better blurring algorithm and uses a bitmap to use an arbitrary
+ * and generally much tighter fitting shape than a rectangle.
+ *
+ * The filter requires 1 argument and has no optional arguments. It requires
+ * a filter bitmap, which must be in PGM or PPM format. A sample invocation would
+ * be -vf remove_logo=/home/username/logo_bitmaps/xyz.pgm. Pixels with a value of
+ * zero are not part of the logo, and non-zero pixels are part of the logo. If you
+ * use white (255) for the logo and black (0) for the rest, you will be safe. For
+ * making the filter bitmap, I recommend taking a screen capture of a black frame
+ * with the logo visible, and then using The GIMP's threshold filter followed by
+ * the erode filter once or twice. If needed, little splotches can be fixed
+ * manually. Remember that if logo pixels are not covered, the filter quality will
+ * be much reduced. Marking too many pixels as part of the logo doesn't hurt as
+ * much, but it will increase the amount of blurring needed to cover over the
+ * image and will destroy more information than necessary. Additionally, this blur
+ * algorithm is O(n) = n^4, where n is the width and height of a hypothetical
+ * square logo, so extra pixels will slow things down on a large lo
+ *
+ * The logo removal algorithm has two key points. The first is that it
+ * distinguishes between pixels in the logo and those not in the logo by using the
+ * passed-in bitmap. Pixels not in the logo are copied over directly without being
+ * modified and they also serve as source pixels for the logo fill-in. Pixels
+ * inside the logo have the mask applied.
+ *
+ * At init-time the bitmap is reprocessed internally, and the distance to the
+ * nearest edge of the logo (Manhattan distance), along with a little extra to
+ * remove rough edges, is stored in each pixel. This is done using an in-place
+ * erosion algorithm, and incrementing each pixel that survives any given erosion.
+ * Once every pixel is eroded, the maximum value is recorded, and a set of masks
+ * from size 0 to this size are generaged. The masks are circular binary masks,
+ * where each pixel within a radius N (where N is the size of the mask) is a 1,
+ * and all other pixels are a 0. Although a gaussian mask would be more
+ * mathematically accurate, a binary mask works better in practice because we
+ * generally do not use the central pixels in the mask (because they are in the
+ * logo region), and thus a gaussian mask will cause too little blur and thus a
+ * very unstable image.
+ *
+ * The mask is applied in a special way. Namely, only pixels in the mask that
+ * line up to pixels outside the logo are used. The dynamic mask size means that
+ * the mask is just big enough so that the edges touch pixels outside the logo, so
+ * the blurring is kept to a minimum and at least the first boundary condition is
+ * met (that the image function itself is continuous), even if the second boundary
+ * condition (that the derivative of the image function is continuous) is not met.
+ * A masking algorithm that does preserve the second boundary coundition
+ * (perhaps something based on a highly-modified bi-cubic algorithm) should offer
+ * even better results on paper, but the noise in a typical TV signal should make
+ * anything based on derivatives hopelessly noisy.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "libvo/fastmemcpy.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+//===========================================================================//
+
+/** \brief Returns the larger of the two arguments. **/
+#define max(x,y) ((x)>(y)?(x):(y))
+/** \brief Returns the smaller of the two arguments. **/
+#define min(x,y) ((x)>(y)?(y):(x))
+
+/**
+ * \brief Test if a pixel is part of the logo.
+ */
+#define test_filter(image, x, y) ((unsigned char) (image->pixel[((y) * image->width) + (x)]))
+
+/**
+ * \brief Chooses a slightly larger mask size to improve performance.
+ *
+ * This function maps the absolute minimum mask size needed to the mask size we'll
+ * actually use. f(x) = x (the smallest that will work) will produce the sharpest
+ * results, but will be quite jittery. f(x) = 1.25x (what I'm using) is a good
+ * tradeoff in my opinion. This will calculate only at init-time, so you can put a
+ * long expression here without effecting performance.
+ */
+#define apply_mask_fudge_factor(x) (((x) >> 2) + x)
+
+/**
+ * \brief Simple implementation of the PGM image format.
+ *
+ * This struct holds a bare-bones image loaded from a PGM or PPM file. Once
+ * loaded and pre-processed, each pixel in this struct will contain how far from
+ * the edge of the logo each pixel is, using the manhattan distance (|dx| + |dy|).
+ *
+ * pixels in char * pixel can be addressed using (y * width) + height.
+ */
+typedef struct
+{
+ unsigned int width;
+ unsigned int height;
+
+ unsigned char * pixel;
+
+} pgm_structure;
+
+/**
+ * \brief Stores persistant variables.
+ *
+ * Variables stored here are kept from frame to frame, and separate instances of
+ * the filter will get their own separate copies.
+ */
+struct vf_priv_s
+{
+ unsigned int fmt; /* Not exactly sure of the use for this. It came with the example filter I used as a basis for this, and it looks like a lot of stuff will break if I remove it. */
+ int max_mask_size; /* The largest possible mask size that will be needed with the given filter and corresponding half_size_filter. The half_size_filter can have a larger requirment in some rare (but not degenerate) cases. */
+ int * * * mask; /* Stores our collection of masks. The first * is for an array of masks, the second for the y axis, and the third for the x axis. */
+ pgm_structure * filter; /* Stores the full-size filter image. This is used to tell what pixels are in the logo or not in the luma plane. */
+ pgm_structure * half_size_filter; /* Stores a 50% width and 50% height filter image. This is used to tell what pixels are in the logo or not in the chroma planes. */
+ /* These 8 variables store the bounding rectangles that the logo resides in. */
+ int bounding_rectangle_posx1;
+ int bounding_rectangle_posy1;
+ int bounding_rectangle_posx2;
+ int bounding_rectangle_posy2;
+ int bounding_rectangle_half_size_posx1;
+ int bounding_rectangle_half_size_posy1;
+ int bounding_rectangle_half_size_posx2;
+ int bounding_rectangle_half_size_posy2;
+} vf_priv_s;
+
+/**
+ * \brief Mallocs memory and checks to make sure it succeeded.
+ *
+ * \param size How many bytes to allocate.
+ *
+ * \return A pointer to the freshly allocated memory block, or NULL on failutre.
+ *
+ * Mallocs memory, and checks to make sure it was successfully allocated. Because
+ * of how MPlayer works, it cannot safely halt execution, but at least the user
+ * will get an error message before the segfault happens.
+ */
+static void * safe_malloc(int size)
+{
+ void * answer = malloc(size);
+ if (answer == NULL)
+ mp_msg(MSGT_VFILTER, MSGL_ERR, "Unable to allocate memory in vf_remove_logo.c\n");
+
+ return answer;
+}
+
+/**
+ * \brief Calculates the smallest rectangle that will encompass the logo region.
+ *
+ * \param filter This image contains the logo around which the rectangle will
+ * will be fitted.
+ *
+ * The bounding rectangle is calculated by testing successive lines (from the four
+ * sides of the rectangle) until no more can be removed without removing logo
+ * pixels. The results are returned by reference to posx1, posy1, posx2, and
+ * posy2.
+ */
+static void calculate_bounding_rectangle(int * posx1, int * posy1, int * posx2, int * posy2, pgm_structure * filter)
+{
+ int x; /* Temporary variables to run */
+ int y; /* through each row or column. */
+ int start_x;
+ int start_y;
+ int end_x = filter->width - 1;
+ int end_y = filter->height - 1;
+ int did_we_find_a_logo_pixel = 0;
+
+ /* Let's find the top bound first. */
+ for (start_x = 0; start_x < filter->width && !did_we_find_a_logo_pixel; start_x++)
+ {
+ for (y = 0; y < filter->height; y++)
+ {
+ did_we_find_a_logo_pixel |= test_filter(filter, start_x, y);
+ }
+ }
+ start_x--;
+
+ /* Now the bottom bound. */
+ did_we_find_a_logo_pixel = 0;
+ for (end_x = filter->width - 1; end_x > start_x && !did_we_find_a_logo_pixel; end_x--)
+ {
+ for (y = 0; y < filter->height; y++)
+ {
+ did_we_find_a_logo_pixel |= test_filter(filter, end_x, y);
+ }
+ }
+ end_x++;
+
+ /* Left bound. */
+ did_we_find_a_logo_pixel = 0;
+ for (start_y = 0; start_y < filter->height && !did_we_find_a_logo_pixel; start_y++)
+ {
+ for (x = 0; x < filter->width; x++)
+ {
+ did_we_find_a_logo_pixel |= test_filter(filter, x, start_y);
+ }
+ }
+ start_y--;
+
+ /* Right bound. */
+ did_we_find_a_logo_pixel = 0;
+ for (end_y = filter->height - 1; end_y > start_y && !did_we_find_a_logo_pixel; end_y--)
+ {
+ for (x = 0; x < filter->width; x++)
+ {
+ did_we_find_a_logo_pixel |= test_filter(filter, x, end_y);
+ }
+ }
+ end_y++;
+
+ *posx1 = start_x;
+ *posy1 = start_y;
+ *posx2 = end_x;
+ *posy2 = end_y;
+
+ return;
+}
+
+/**
+ * \brief Free mask memory.
+ *
+ * \param vf Data structure which stores our persistant data, and is to be freed.
+ *
+ * We call this function when our filter is done. It will free the memory
+ * allocated to the masks and leave the variables in a safe state.
+ */
+static void destroy_masks(vf_instance_t * vf)
+{
+ int a, b;
+
+ /* Load values from the vf->priv struct for faster dereferencing. */
+ int * * * mask = vf->priv->mask;
+ int max_mask_size = vf->priv->max_mask_size;
+
+ if (mask == NULL)
+ return; /* Nothing allocated, so return before we segfault. */
+
+ /* Free all allocated memory. */
+ for (a = 0; a <= max_mask_size; a++) /* Loop through each mask. */
+ {
+ for (b = -a; b <= a; b++) /* Loop through each scanline in a mask. */
+ {
+ free(mask[a][b + a]); /* Free a scanline. */
+ }
+ free(mask[a]); /* Free a mask. */
+ }
+ free(mask); /* Free the array of pointers pointing to the masks. */
+
+ /* Set the pointer to NULL, so that any duplicate calls to this function will not cause a crash. */
+ vf->priv->mask = NULL;
+
+ return;
+}
+
+/**
+ * \brief Set up our array of masks.
+ *
+ * \param vf Where our filter stores persistance data, like these masks.
+ *
+ * This creates an array of progressively larger masks and calculates their
+ * values. The values will not change during program execution once this function
+ * is done.
+ */
+static void initialize_masks(vf_instance_t * vf)
+{
+ int a, b, c;
+
+ /* Load values from the vf->priv struct for faster dereferencing. */
+ int * * * mask = vf->priv->mask;
+ int max_mask_size = vf->priv->max_mask_size; /* This tells us how many masks we'll need to generate. */
+
+ /* Create a circular mask for each size up to max_mask_size. When the filter is applied, the mask size is
+ determined on a pixel by pixel basis, with pixels nearer the edge of the logo getting smaller mask sizes. */
+ mask = (int * * *) safe_malloc(sizeof(int * *) * (max_mask_size + 1));
+ for (a = 0; a <= max_mask_size; a++)
+ {
+ mask[a] = (int * *) safe_malloc(sizeof(int *) * ((a * 2) + 1));
+ for (b = -a; b <= a; b++)
+ {
+ mask[a][b + a] = (int *) safe_malloc(sizeof(int) * ((a * 2) + 1));
+ for (c = -a; c <= a; c++)
+ {
+ if ((b * b) + (c * c) <= (a * a)) /* Circular 0/1 mask. */
+ mask[a][b + a][c + a] = 1;
+ else
+ mask[a][b + a][c + a] = 0;
+ }
+ }
+ }
+
+ /* Store values back to vf->priv so they aren't lost after the function returns. */
+ vf->priv->mask = mask;
+
+ return;
+}
+
+/**
+ * \brief Pre-processes an image to give distance information.
+ *
+ * \param vf Data structure that holds persistant information. All it is used for
+ in this function is to store the calculated max_mask_size variable.
+ * \param mask This image will be converted from a greyscale image into a
+ * distance image.
+ *
+ * This function takes a greyscale image (pgm_structure * mask) and converts it
+ * in place into a distance image. A distance image is zero for pixels ourside of
+ * the logo and is the manhattan distance (|dx| + |dy|) for pixels inside of the
+ * logo. This will overestimate the distance, but that is safe, and is far easier
+ * to implement than a proper pythagorean distance since I'm using a modified
+ * erosion algorithm to compute the distances.
+ */
+static void convert_mask_to_strength_mask(vf_instance_t * vf, pgm_structure * mask)
+{
+ int x, y; /* Used by our for loops to go through every single pixel in the picture one at a time. */
+ int has_anything_changed = 1; /* Used by the main while() loop to know if anything changed on the last erosion. */
+ int current_pass = 0; /* How many times we've gone through the loop. Used in the in-place erosion algorithm
+ and to get us max_mask_size later on. */
+ int max_mask_size; /* This will record how large a mask the pixel that is the furthest from the edge of the logo
+ (and thus the neediest) is. */
+ char * current_pixel = mask->pixel; /* This stores the actual pixel data. */
+
+ /* First pass, set all non-zero values to 1. After this loop finishes, the data should be considered numeric
+ data for the filter, not color data. */
+ for (x = 0; x < mask->height * mask->width; x++, current_pixel++)
+ if(*current_pixel) *current_pixel = 1;
+
+ /* Second pass and future passes. For each pass, if a pixel is itself the same value as the current pass,
+ and its four neighbors are too, then it is incremented. If no pixels are incremented by the end of the pass,
+ then we go again. Edge pixels are counted as always excluded (this should be true anyway for any sane mask,
+ but if it isn't this will ensure that we eventually exit). */
+ while (has_anything_changed)
+ {
+ current_pass++;
+ current_pixel = mask->pixel;
+
+ has_anything_changed = 0; /* If this doesn't get set by the end of this pass, then we're done. */
+
+ for (y = 1; y < mask->height - 1; y++)
+ {
+ for (x = 1; x < mask->width - 1; x++)
+ {
+ /* Apply the in-place erosion transform. It is based on the following two premises: 1 - Any pixel that fails 1 erosion
+ will fail all future erosions. 2 - Only pixels having survived all erosions up to the present will be >= to
+ current_pass. It doesn't matter if it survived the current pass, failed it, or hasn't been tested yet. */
+ if (*current_pixel >= current_pass && /* By using >= instead of ==, we allow the algorithm to work in place. */
+ *(current_pixel + 1) >= current_pass &&
+ *(current_pixel - 1) >= current_pass &&
+ *(current_pixel + mask->width) >= current_pass &&
+ *(current_pixel - mask->width) >= current_pass)
+ {
+ (*current_pixel)++; /* Increment the value since it still has not been eroded, as evidenced by the if statement
+ that just evaluated to true. */
+ has_anything_changed = 1;
+ }
+ current_pixel++;
+ }
+ }
+ }
+
+ /* Apply the fudge factor, which will increase the size of the mask a little to reduce jitter at the cost of more blur. */
+ for (y = 1; y < mask->height - 1; y++)
+ {
+ for (x = 1; x < mask->width - 1; x++)
+ {
+ mask->pixel[(y * mask->width) + x] = apply_mask_fudge_factor(mask->pixel[(y * mask->width) + x]);
+ }
+ }
+
+ max_mask_size = current_pass + 1; /* As a side-effect, we now know the maximum mask size, which we'll use to generate our masks. */
+ max_mask_size = apply_mask_fudge_factor(max_mask_size); /* Apply the fudge factor to this number too, since we must
+ ensure that enough masks are generated. */
+ vf->priv->max_mask_size = max_mask_size; /* Commit the newly calculated max_mask_size to the vf->priv struct. */
+
+ return;
+}
+
+/**
+ * \brief Our blurring function.
+ *
+ * \param vf Stores persistant data. In this function we are interested in the
+ * array of masks.
+ * \param value_out The properly blurred and delogoed pixel is outputted here.
+ * \param logo_mask Tells us which pixels are in the logo and which aren't.
+ * \param image The image that is having its logo removed.
+ * \param x x-coordinate of the pixel to blur.
+ * \param y y-coordinate of the pixel to blur.
+ * \param plane 0 = luma, 1 = blue chroma, 2 = red chroma (YUV).
+ *
+ * This function is the core of the filter. It takes a pixel that is inside the
+ * logo and blurs it. It does so by finding the average of all the pixels within
+ * the mask and outside of the logo.
+ */
+static void get_blur(const vf_instance_t * const vf, unsigned int * const value_out, const pgm_structure * const logo_mask,
+ const mp_image_t * const image, const int x, const int y, const int plane)
+{
+ int mask_size; /* Mask size tells how large a circle to use. The radius is about (slightly larger than) mask size. */
+ /* Get values from vf->priv for faster dereferencing. */
+ int * * * mask = vf->priv->mask;
+
+ int start_posx, start_posy, end_posx, end_posy;
+ int i, j;
+ unsigned int accumulator = 0, divisor = 0;
+ const unsigned char * mask_read_position; /* What pixel we are reading out of the circular blur mask. */
+ const unsigned char * logo_mask_read_position; /* What pixel we are reading out of the filter image. */
+
+ /* Prepare our bounding rectangle and clip it if need be. */
+ mask_size = test_filter(logo_mask, x, y);
+ start_posx = max(0, x - mask_size);
+ start_posy = max(0, y - mask_size);
+ end_posx = min(image->width - 1, x + mask_size);
+ end_posy = min(image->height - 1, y + mask_size);
+
+ mask_read_position = image->planes[plane] + (image->stride[plane] * start_posy) + start_posx;
+ logo_mask_read_position = logo_mask->pixel + (start_posy * logo_mask->width) + start_posx;
+
+ for (j = start_posy; j <= end_posy; j++)
+ {
+ for (i = start_posx; i <= end_posx; i++)
+ {
+ if (!(*logo_mask_read_position) && mask[mask_size][i - start_posx][j - start_posy])
+ { /* Check to see if this pixel is in the logo or not. Only use the pixel if it is not. */
+ accumulator += *mask_read_position;
+ divisor++;
+ }
+
+ mask_read_position++;
+ logo_mask_read_position++;
+ }
+
+ mask_read_position += (image->stride[plane] - ((end_posx + 1) - start_posx));
+ logo_mask_read_position += (logo_mask->width - ((end_posx + 1) - start_posx));
+ }
+
+ if (divisor == 0) /* This means that not a single pixel is outside of the logo, so we have no data. */
+ { /* We should put some eye catching value here, to indicate the flaw to the user. */
+ *value_out = 255;
+ }
+ else /* Else we need to normalise the data using the divisor. */
+ {
+ *value_out = (accumulator + (divisor / 2)) / divisor; /* Divide, taking into account average rounding error. */
+ }
+
+ return;
+}
+
+/**
+ * \brief Free a pgm_structure. Undoes load_pgm(...).
+ */
+static void destroy_pgm(pgm_structure * to_be_destroyed)
+{
+ if (to_be_destroyed == NULL)
+ return; /* Don't do anything if a NULL pointer was passed it. */
+
+ /* Internally allocated memory. */
+ if (to_be_destroyed->pixel != NULL)
+ {
+ free(to_be_destroyed->pixel);
+ to_be_destroyed->pixel = NULL;
+ }
+
+ /* Free the actual struct instance. This is done here and not by the calling function. */
+ free(to_be_destroyed);
+}
+
+/** \brief Helper function for load_pgm(...) to skip whitespace. */
+static void load_pgm_skip(FILE *f) {
+ int c, comment = 0;
+ do {
+ c = fgetc(f);
+ if (c == '#')
+ comment = 1;
+ if (c == '\n')
+ comment = 0;
+ } while (c != EOF && (isspace(c) || comment));
+ ungetc(c, f);
+}
+
+#define REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE(message) {mp_msg(MSGT_VFILTER, MSGL_ERR, message); return NULL;}
+
+/**
+ * \brief Loads a raw pgm or ppm file into a newly created pgm_structure object.
+ *
+ * \param file_name The name of the file to be loaded. So long as the file is a
+ * valid pgm or ppm file, it will load correctly, even if the
+ * extension is missing or invalid.
+ *
+ * \return A pointer to the newly created pgm_structure object. Don't forget to
+ * call destroy_pgm(...) when you're done with this. If an error occurs,
+ * NULL is returned.
+ *
+ * Can load either raw pgm (P5) or raw ppm (P6) image files as a binary image.
+ * While a pgm file will be loaded normally (greyscale), the only thing that is
+ * guaranteed with ppm is that all zero (R = 0, G = 0, B = 0) pixels will remain
+ * zero, and non-zero pixels will remain non-zero.
+ */
+static pgm_structure * load_pgm(const char * file_name)
+{
+ int maximum_greyscale_value;
+ FILE * input;
+ int pnm_number;
+ pgm_structure * new_pgm = (pgm_structure *) safe_malloc (sizeof(pgm_structure));
+ char * write_position;
+ char * end_position;
+ int image_size; /* width * height */
+
+ if((input = fopen(file_name, "rb")) == NULL) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Unable to open file. File not found or insufficient permissions.\n");
+
+ /* Parse the PGM header. */
+ if (fgetc(input) != 'P') REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: File is not a valid PGM or PPM file.\n");
+ pnm_number = fgetc(input) - '0';
+ if (pnm_number != 5 && pnm_number != 6) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PNM file. Only raw PGM (Portable Gray Map) and raw PPM (Portable Pixel Map) subtypes are allowed.\n");
+ load_pgm_skip(input);
+ if (fscanf(input, "%i", &(new_pgm->width)) != 1) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PGM/PPM header.\n");
+ load_pgm_skip(input);
+ if (fscanf(input, "%i", &(new_pgm->height)) != 1) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PGM/PPM header.\n");
+ load_pgm_skip(input);
+ if (fscanf(input, "%i", &maximum_greyscale_value) != 1) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove-logo: Invalid PGM/PPM header.\n");
+ if (maximum_greyscale_value >= 256) REMOVE_LOGO_LOAD_PGM_ERROR_MESSAGE("[vf]remove_logo: Only 1 byte per pixel (pgm) or 1 byte per color value (ppm) are supported.\n");
+ load_pgm_skip(input);
+
+ new_pgm->pixel = (unsigned char *) safe_malloc (sizeof(unsigned char) * new_pgm->width * new_pgm->height);
+
+ /* Load the pixels. */
+ /* Note: I am aware that fgetc(input) isn't the fastest way of doing things, but it is quite compact and the code only runs once when the filter is initialized.*/
+ image_size = new_pgm->width * new_pgm->height;
+ end_position = new_pgm->pixel + image_size;
+ for (write_position = new_pgm->pixel; write_position < end_position; write_position++)
+ {
+ *write_position = fgetc(input);
+ if (pnm_number == 6) /* This tests to see if the file is a PPM file. */
+ { /* If it is, then consider the pixel set if any of the three color channels are set. Since we just care about == 0 or != 0, a bitwise or will do the trick. */
+ *write_position |= fgetc(input);
+ *write_position |= fgetc(input);
+ }
+ }
+
+ return new_pgm;
+}
+
+/**
+ * \brief Generates a scaled down image with half width, height, and intensity.
+ *
+ * \param vf Our struct for persistant data. In this case, it is used to update
+ * mask_max_size with the larger of the old or new value.
+ * \param input_image The image from which the new half-sized one will be based.
+ *
+ * \return The newly allocated and shrunken image.
+ *
+ * This function not only scales down an image, but halves the value in each pixel
+ * too. The purpose of this is to produce a chroma filter image out of a luma
+ * filter image. The pixel values store the distance to the edge of the logo and
+ * halving the dimensions halves the distance. This function rounds up, because
+ * a downwards rounding error could cause the filter to fail, but an upwards
+ * rounding error will only cause a minor amount of excess blur in the chroma
+ * planes.
+ */
+static pgm_structure * generate_half_size_image(vf_instance_t * vf, pgm_structure * input_image)
+{
+ int x, y;
+ pgm_structure * new_pgm = (pgm_structure *) safe_malloc (sizeof(pgm_structure));
+ int has_anything_changed = 1;
+ int current_pass;
+ int max_mask_size;
+ char * current_pixel;
+
+ new_pgm->width = input_image->width / 2;
+ new_pgm->height = input_image->height / 2;
+ new_pgm->pixel = (unsigned char *) safe_malloc (sizeof(unsigned char) * new_pgm->width * new_pgm->height);
+
+ /* Copy over the image data, using the average of 4 pixels for to calculate each downsampled pixel. */
+ for (y = 0; y < new_pgm->height; y++)
+ for (x = 0; x < new_pgm->width; x++)
+ {
+ /* Set the pixel if there exists a non-zero value in the source pixels, else clear it. */
+ new_pgm->pixel[(y * new_pgm->width) + x] = input_image->pixel[((y << 1) * input_image->width) + (x << 1)] ||
+ input_image->pixel[((y << 1) * input_image->width) + (x << 1) + 1] ||
+ input_image->pixel[(((y << 1) + 1) * input_image->width) + (x << 1)] ||
+ input_image->pixel[(((y << 1) + 1) * input_image->width) + (x << 1) + 1];
+ new_pgm->pixel[(y * new_pgm->width) + x] = min(1, new_pgm->pixel[(y * new_pgm->width) + x]);
+ }
+
+ /* Now we need to recalculate the numbers for the smaller size. Just using the old_value / 2 can cause subtle
+ and fairly rare, but very nasty, bugs. */
+
+ current_pixel = new_pgm->pixel;
+ /* First pass, set all non-zero values to 1. */
+ for (x = 0; x < new_pgm->height * new_pgm->width; x++, current_pixel++)
+ if(*current_pixel) *current_pixel = 1;
+
+ /* Second pass and future passes. For each pass, if a pixel is itself the same value as the current pass,
+ and its four neighbors are too, then it is incremented. If no pixels are incremented by the end of the pass,
+ then we go again. Edge pixels are counted as always excluded (this should be true anyway for any sane mask,
+ but if it isn't this will ensure that we eventually exit). */
+ current_pass = 0;
+ while (has_anything_changed)
+ {
+ current_pass++;
+
+ has_anything_changed = 0; /* If this doesn't get set by the end of this pass, then we're done. */
+
+ for (y = 1; y < new_pgm->height - 1; y++)
+ {
+ for (x = 1; x < new_pgm->width - 1; x++)
+ {
+ if (new_pgm->pixel[(y * new_pgm->width) + x] >= current_pass && /* By using >= instead of ==, we allow the algorithm to work in place. */
+ new_pgm->pixel[(y * new_pgm->width) + (x + 1)] >= current_pass &&
+ new_pgm->pixel[(y * new_pgm->width) + (x - 1)] >= current_pass &&
+ new_pgm->pixel[((y + 1) * new_pgm->width) + x] >= current_pass &&
+ new_pgm->pixel[((y - 1) * new_pgm->width) + x] >= current_pass)
+ {
+ new_pgm->pixel[(y * new_pgm->width) + x]++; /* Increment the value since it still has not been eroded,
+ as evidenced by the if statement that just evaluated to true. */
+ has_anything_changed = 1;
+ }
+ }
+ }
+ }
+
+ for (y = 1; y < new_pgm->height - 1; y++)
+ {
+ for (x = 1; x < new_pgm->width - 1; x++)
+ {
+ new_pgm->pixel[(y * new_pgm->width) + x] = apply_mask_fudge_factor(new_pgm->pixel[(y * new_pgm->width) + x]);
+ }
+ }
+
+ max_mask_size = current_pass + 1; /* As a side-effect, we now know the maximum mask size, which we'll use to generate our masks. */
+ max_mask_size = apply_mask_fudge_factor(max_mask_size);
+ /* Commit the newly calculated max_mask_size to the vf->priv struct. */
+ vf->priv->max_mask_size = max(max_mask_size, vf->priv->max_mask_size);
+
+ return new_pgm;
+}
+
+/**
+ * \brief Checks if YV12 is supported by the next filter.
+ */
+static unsigned int find_best(struct vf_instance *vf){
+ int is_format_okay = vf->next->query_format(vf->next, IMGFMT_YV12);
+ if ((is_format_okay & VFCAP_CSP_SUPPORTED_BY_HW) || (is_format_okay & VFCAP_CSP_SUPPORTED))
+ return IMGFMT_YV12;
+ else
+ return 0;
+}
+
+//===========================================================================//
+
+/**
+ * \brief Configure the filter and call the next filter's config function.
+ */
+static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt)
+{
+ if(!(vf->priv->fmt=find_best(vf)))
+ return 0;
+ else
+ return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
+}
+
+/**
+ * \brief Removes the logo from a plane (either luma or chroma).
+ *
+ * \param vf Not needed by this function, but needed by the blur function.
+ * \param source The image to have it's logo removed.
+ * \param destination Where the output image will be stored.
+ * \param source_stride How far apart (in memory) two consecutive lines are.
+ * \param destination Same as source_stride, but for the destination image.
+ * \param width Width of the image. This is the same for source and destination.
+ * \param height Height of the image. This is the same for source and destination.
+ * \param is_image_direct If the image is direct, then source and destination are
+ * the same and we can save a lot of time by not copying pixels that
+ * haven't changed.
+ * \param filter The image that stores the distance to the edge of the logo for
+ * each pixel.
+ * \param logo_start_x Smallest x-coordinate that contains at least 1 logo pixel.
+ * \param logo_start_y Smallest y-coordinate that contains at least 1 logo pixel.
+ * \param logo_end_x Largest x-coordinate that contains at least 1 logo pixel.
+ * \param logo_end_y Largest y-coordinate that contains at least 1 logo pixel.
+ *
+ * This function processes an entire plane. Pixels outside of the logo are copied
+ * to the output without change, and pixels inside the logo have the de-blurring
+ * function applied.
+ */
+static void convert_yv12(const vf_instance_t * const vf, const char * const source, const int source_stride,
+ const mp_image_t * const source_image, const int width, const int height,
+ char * const destination, const int destination_stride, int is_image_direct, pgm_structure * filter,
+ const int plane, const int logo_start_x, const int logo_start_y, const int logo_end_x, const int logo_end_y)
+{
+ int y;
+ int x;
+
+ /* These pointers point to where we are getting our pixel data (inside mpi) and where we are storing it (inside dmpi). */
+ const unsigned char * source_line;
+ unsigned char * destination_line;
+
+ if (!is_image_direct)
+ memcpy_pic(destination, source, width, height, destination_stride, source_stride);
+
+ for (y = logo_start_y; y <= logo_end_y; y++)
+ {
+ source_line = (const unsigned char *) source + (source_stride * y);
+ destination_line = (unsigned char *) destination + (destination_stride * y);
+
+ for (x = logo_start_x; x <= logo_end_x; x++)
+ {
+ unsigned int output;
+
+ if (filter->pixel[(y * filter->width) + x]) /* Only process if we are in the logo. */
+ {
+ get_blur(vf, &output, filter, source_image, x, y, plane);
+ destination_line[x] = output;
+ }
+ else /* Else just copy the data. */
+ if (!is_image_direct)
+ destination_line[x] = source_line[x];
+ }
+ }
+}
+
+/**
+ * \brief Process a frame.
+ *
+ * \param mpi The image sent to use by the previous filter.
+ * \param dmpi Where we will store the processed output image.
+ * \param vf This is how the filter gets access to it's persistant data.
+ *
+ * \return The return code of the next filter, or 0 on failure/error.
+ *
+ * This function processes an entire frame. The frame is sent by the previous
+ * filter, has the logo removed by the filter, and is then sent to the next
+ * filter.
+ */
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ dmpi=vf_get_image(vf->next,vf->priv->fmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w, mpi->h);
+
+ /* Check to make sure that the filter image and the video stream are the same size. */
+ if (vf->priv->filter->width != mpi->w || vf->priv->filter->height != mpi->h)
+ {
+ mp_msg(MSGT_VFILTER,MSGL_ERR, "Filter image and video stream are not of the same size. (Filter: %d x %d, Stream: %d x %d)\n",
+ vf->priv->filter->width, vf->priv->filter->height, mpi->w, mpi->h);
+ return 0;
+ }
+
+ switch(dmpi->imgfmt){
+ case IMGFMT_YV12:
+ convert_yv12(vf, mpi->planes[0], mpi->stride[0], mpi, mpi->w, mpi->h,
+ dmpi->planes[0], dmpi->stride[0],
+ mpi->flags & MP_IMGFLAG_DIRECT, vf->priv->filter, 0,
+ vf->priv->bounding_rectangle_posx1, vf->priv->bounding_rectangle_posy1,
+ vf->priv->bounding_rectangle_posx2, vf->priv->bounding_rectangle_posy2);
+ convert_yv12(vf, mpi->planes[1], mpi->stride[1], mpi, mpi->w / 2, mpi->h / 2,
+ dmpi->planes[1], dmpi->stride[1],
+ mpi->flags & MP_IMGFLAG_DIRECT, vf->priv->half_size_filter, 1,
+ vf->priv->bounding_rectangle_half_size_posx1, vf->priv->bounding_rectangle_half_size_posy1,
+ vf->priv->bounding_rectangle_half_size_posx2, vf->priv->bounding_rectangle_half_size_posy2);
+ convert_yv12(vf, mpi->planes[2], mpi->stride[2], mpi, mpi->w / 2, mpi->h / 2,
+ dmpi->planes[2], dmpi->stride[2],
+ mpi->flags & MP_IMGFLAG_DIRECT, vf->priv->half_size_filter, 2,
+ vf->priv->bounding_rectangle_half_size_posx1, vf->priv->bounding_rectangle_half_size_posy1,
+ vf->priv->bounding_rectangle_half_size_posx2, vf->priv->bounding_rectangle_half_size_posy2);
+ break;
+
+ default:
+ mp_msg(MSGT_VFILTER,MSGL_ERR,"Unhandled format: 0x%X\n",dmpi->imgfmt);
+ return 0;
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+/**
+ * \brief Checks to see if the next filter accepts YV12 images.
+ */
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ if (fmt == IMGFMT_YV12)
+ return vf->next->query_format(vf->next, IMGFMT_YV12);
+ else
+ return 0;
+}
+
+/**
+ * \brief Frees memory that our filter allocated.
+ *
+ * This is called at exit-time.
+ */
+static void uninit(vf_instance_t *vf)
+{
+ /* Destroy our masks and images. */
+ destroy_pgm(vf->priv->filter);
+ destroy_pgm(vf->priv->half_size_filter);
+ destroy_masks(vf);
+
+ /* Destroy our private structure that had been used to store those masks and images. */
+ free(vf->priv);
+
+ return;
+}
+
+/**
+ * \brief Initializes our filter.
+ *
+ * \param args The arguments passed in from the command line go here. This
+ * filter expects only a single argument telling it where the PGM
+ * or PPM file that describes the logo region is.
+ *
+ * This sets up our instance variables and parses the arguments to the filter.
+ */
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->priv = safe_malloc(sizeof(vf_priv_s));
+ vf->uninit = uninit;
+
+ /* Load our filter image. */
+ if (args)
+ vf->priv->filter = load_pgm(args);
+ else
+ {
+ mp_msg(MSGT_VFILTER, MSGL_ERR, "[vf]remove_logo usage: remove_logo=/path/to/filter_image_file.pgm\n");
+ free(vf->priv);
+ return 0;
+ }
+
+ if (vf->priv->filter == NULL)
+ {
+ /* Error message was displayed by load_pgm(). */
+ free(vf->priv);
+ return 0;
+ }
+
+ /* Create the scaled down filter image for the chroma planes. */
+ convert_mask_to_strength_mask(vf, vf->priv->filter);
+ vf->priv->half_size_filter = generate_half_size_image(vf, vf->priv->filter);
+
+ /* Now that we know how many masks we need (the info is in vf), we can generate the masks. */
+ initialize_masks(vf);
+
+ /* Calculate our bounding rectangles, which determine in what region the logo resides for faster processing. */
+ calculate_bounding_rectangle(&vf->priv->bounding_rectangle_posx1, &vf->priv->bounding_rectangle_posy1,
+ &vf->priv->bounding_rectangle_posx2, &vf->priv->bounding_rectangle_posy2,
+ vf->priv->filter);
+ calculate_bounding_rectangle(&vf->priv->bounding_rectangle_half_size_posx1,
+ &vf->priv->bounding_rectangle_half_size_posy1,
+ &vf->priv->bounding_rectangle_half_size_posx2,
+ &vf->priv->bounding_rectangle_half_size_posy2,
+ vf->priv->half_size_filter);
+
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ return 1;
+}
+
+/**
+ * \brief Meta data about our filter.
+ */
+const vf_info_t vf_info_remove_logo = {
+ "Removes a tv logo based on a mask image.",
+ "remove-logo",
+ "Robert Edele",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_rgbtest.c b/libavfilter/libmpcodecs/vf_rgbtest.c
new file mode 100644
index 0000000000..cbed6ed367
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_rgbtest.c
@@ -0,0 +1,171 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+//===========================================================================//
+
+struct vf_priv_s {
+ unsigned int fmt;
+ int w, h;
+};
+
+static unsigned int getfmt(unsigned int outfmt){
+ switch(outfmt){
+ case IMGFMT_RGB12:
+ case IMGFMT_RGB15:
+ case IMGFMT_RGB16:
+ case IMGFMT_RGB24:
+ case IMGFMT_RGBA:
+ case IMGFMT_ARGB:
+ case IMGFMT_BGR12:
+ case IMGFMT_BGR15:
+ case IMGFMT_BGR16:
+ case IMGFMT_BGR24:
+ case IMGFMT_BGRA:
+ case IMGFMT_ABGR:
+ return outfmt;
+ }
+ return 0;
+}
+
+static void put_pixel(uint8_t *buf, int x, int y, int stride, int r, int g, int b, int fmt){
+ switch(fmt){
+ case IMGFMT_BGR12: ((uint16_t*)(buf + y*stride))[x]=
+ ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4);
+ break;
+ case IMGFMT_RGB12: ((uint16_t*)(buf + y*stride))[x]=
+ ((b >> 4) << 8) | ((g >> 4) << 4) | (r >> 4);
+ break;
+ case IMGFMT_BGR15: ((uint16_t*)(buf + y*stride))[x]= ((r>>3)<<10) | ((g>>3)<<5) | (b>>3);
+ break;
+ case IMGFMT_RGB15: ((uint16_t*)(buf + y*stride))[x]= ((b>>3)<<10) | ((g>>3)<<5) | (r>>3);
+ break;
+ case IMGFMT_BGR16: ((uint16_t*)(buf + y*stride))[x]= ((r>>3)<<11) | ((g>>2)<<5) | (b>>3);
+ break;
+ case IMGFMT_RGB16: ((uint16_t*)(buf + y*stride))[x]= ((b>>3)<<11) | ((g>>2)<<5) | (r>>3);
+ break;
+ case IMGFMT_RGB24:
+ buf[3*x + y*stride + 0]= r;
+ buf[3*x + y*stride + 1]= g;
+ buf[3*x + y*stride + 2]= b;
+ break;
+ case IMGFMT_BGR24:
+ buf[3*x + y*stride + 0]= b;
+ buf[3*x + y*stride + 1]= g;
+ buf[3*x + y*stride + 2]= r;
+ break;
+ case IMGFMT_RGBA:
+ buf[4*x + y*stride + 0]= r;
+ buf[4*x + y*stride + 1]= g;
+ buf[4*x + y*stride + 2]= b;
+ break;
+ case IMGFMT_BGRA:
+ buf[4*x + y*stride + 0]= b;
+ buf[4*x + y*stride + 1]= g;
+ buf[4*x + y*stride + 2]= r;
+ break;
+ case IMGFMT_ARGB:
+ buf[4*x + y*stride + 1]= r;
+ buf[4*x + y*stride + 2]= g;
+ buf[4*x + y*stride + 3]= b;
+ break;
+ case IMGFMT_ABGR:
+ buf[4*x + y*stride + 1]= b;
+ buf[4*x + y*stride + 2]= g;
+ buf[4*x + y*stride + 3]= r;
+ break;
+ }
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ if (vf->priv->w > 0) { d_width = width = vf->priv->w; }
+ if (vf->priv->h > 0) { d_height = height = vf->priv->h; }
+ vf->priv->fmt=getfmt(outfmt);
+ mp_msg(MSGT_VFILTER,MSGL_V,"rgb test format:%s\n", vo_format_name(outfmt));
+ return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ int x, y;
+ int w = vf->priv->w > 0 ? vf->priv->w : mpi->w;
+ int h = vf->priv->h > 0 ? vf->priv->h : mpi->h;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,vf->priv->fmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ w, h);
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int c= 256*x/w;
+ int r=0,g=0,b=0;
+
+ if(3*y<h) r=c;
+ else if(3*y<2*h) g=c;
+ else b=c;
+
+ put_pixel(dmpi->planes[0], x, y, dmpi->stride[0], r, g, b, vf->priv->fmt);
+ }
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int outfmt){
+ unsigned int fmt=getfmt(outfmt);
+ if(!fmt) return 0;
+ return vf_next_query_format(vf,fmt) & (~VFCAP_CSP_SUPPORTED_BY_HW);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ vf->priv->w = vf->priv->h = 0;
+ if (args)
+ sscanf(args, "%d:%d", &vf->priv->w, &vf->priv->h);
+ return 1;
+}
+
+const vf_info_t vf_info_rgbtest = {
+ "rgbtest",
+ "rgbtest",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_rotate.c b/libavfilter/libmpcodecs/vf_rotate.c
new file mode 100644
index 0000000000..08d73bec28
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_rotate.c
@@ -0,0 +1,152 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ int direction;
+};
+
+static void rotate(unsigned char* dst,unsigned char* src,int dststride,int srcstride,int w,int h,int bpp,int dir){
+ int y;
+ if(dir&1){
+ src+=srcstride*(w-1);
+ srcstride*=-1;
+ }
+ if(dir&2){
+ dst+=dststride*(h-1);
+ dststride*=-1;
+ }
+
+ for(y=0;y<h;y++){
+ int x;
+ switch(bpp){
+ case 1:
+ for(x=0;x<w;x++) dst[x]=src[y+x*srcstride];
+ break;
+ case 2:
+ for(x=0;x<w;x++) *((short*)(dst+x*2))=*((short*)(src+y*2+x*srcstride));
+ break;
+ case 3:
+ for(x=0;x<w;x++){
+ dst[x*3+0]=src[0+y*3+x*srcstride];
+ dst[x*3+1]=src[1+y*3+x*srcstride];
+ dst[x*3+2]=src[2+y*3+x*srcstride];
+ }
+ break;
+ case 4:
+ for(x=0;x<w;x++) *((int*)(dst+x*4))=*((int*)(src+y*4+x*srcstride));
+ }
+ dst+=dststride;
+ }
+}
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ if (vf->priv->direction & 4) {
+ if (width<height) vf->priv->direction&=3;
+ }
+ if (vf->priv->direction & 4){
+ vf->put_image=vf_next_put_image; // passthru mode!
+ if (vf->next->draw_slice) vf->draw_slice=vf_next_draw_slice;
+/* FIXME: this should be in an other procedure in vf.c; that should always check
+ whether the filter after the passthrough one still (not)supports slices */
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+ }
+ return vf_next_config(vf,height,width,d_height,d_width,flags,outfmt);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->h, mpi->w);
+
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ rotate(dmpi->planes[0],mpi->planes[0],
+ dmpi->stride[0],mpi->stride[0],
+ dmpi->w,dmpi->h,1,vf->priv->direction);
+ rotate(dmpi->planes[1],mpi->planes[1],
+ dmpi->stride[1],mpi->stride[1],
+ dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,vf->priv->direction);
+ rotate(dmpi->planes[2],mpi->planes[2],
+ dmpi->stride[2],mpi->stride[2],
+ dmpi->w>>mpi->chroma_x_shift,dmpi->h>>mpi->chroma_y_shift,1,vf->priv->direction);
+ } else {
+ rotate(dmpi->planes[0],mpi->planes[0],
+ dmpi->stride[0],mpi->stride[0],
+ dmpi->w,dmpi->h,dmpi->bpp>>3,vf->priv->direction);
+ dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette
+ }
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ if(IMGFMT_IS_RGB(fmt) || IMGFMT_IS_BGR(fmt)) return vf_next_query_format(vf, fmt);
+ // we can support only symmetric (chroma_x_shift==chroma_y_shift) YUV formats:
+ switch(fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+// case IMGFMT_IF09:
+ case IMGFMT_Y8:
+ case IMGFMT_Y800:
+ case IMGFMT_444P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ vf->priv->direction=args?atoi(args):0;
+ return 1;
+}
+
+const vf_info_t vf_info_rotate = {
+ "rotate",
+ "rotate",
+ "A'rpi",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_sab.c b/libavfilter/libmpcodecs/vf_sab.c
new file mode 100644
index 0000000000..75834dc858
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_sab.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "libavutil/avutil.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libswscale/swscale.h"
+#include "vf_scale.h"
+
+
+//===========================================================================//
+
+typedef struct FilterParam{
+ float radius;
+ float preFilterRadius;
+ float strength;
+ float quality;
+ struct SwsContext *preFilterContext;
+ uint8_t *preFilterBuf;
+ int preFilterStride;
+ int distWidth;
+ int distStride;
+ int *distCoeff;
+ int colorDiffCoeff[512];
+}FilterParam;
+
+struct vf_priv_s {
+ FilterParam luma;
+ FilterParam chroma;
+};
+
+
+/***************************************************************************/
+
+//FIXME stupid code duplication
+static void getSubSampleFactors(int *h, int *v, int format){
+ switch(format){
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ *h=1;
+ *v=1;
+ break;
+ case IMGFMT_YVU9:
+ *h=2;
+ *v=2;
+ break;
+ case IMGFMT_444P:
+ *h=0;
+ *v=0;
+ break;
+ case IMGFMT_422P:
+ *h=1;
+ *v=0;
+ break;
+ case IMGFMT_411P:
+ *h=2;
+ *v=0;
+ break;
+ }
+}
+
+static int allocStuff(FilterParam *f, int width, int height){
+ int stride= (width+7)&~7;
+ SwsVector *vec;
+ SwsFilter swsF;
+ int i,x,y;
+ f->preFilterBuf= (uint8_t*)memalign(8, stride*height);
+ f->preFilterStride= stride;
+
+ vec = sws_getGaussianVec(f->preFilterRadius, f->quality);
+ swsF.lumH= swsF.lumV= vec;
+ swsF.chrH= swsF.chrV= NULL;
+ f->preFilterContext= sws_getContext(
+ width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, get_sws_cpuflags()|SWS_POINT, &swsF, NULL, NULL);
+
+ sws_freeVec(vec);
+ vec = sws_getGaussianVec(f->strength, 5.0);
+ for(i=0; i<512; i++){
+ double d;
+ int index= i-256 + vec->length/2;
+
+ if(index<0 || index>=vec->length) d= 0.0;
+ else d= vec->coeff[index];
+
+ f->colorDiffCoeff[i]= (int)(d/vec->coeff[vec->length/2]*(1<<12) + 0.5);
+ }
+ sws_freeVec(vec);
+ vec = sws_getGaussianVec(f->radius, f->quality);
+ f->distWidth= vec->length;
+ f->distStride= (vec->length+7)&~7;
+ f->distCoeff= (int32_t*)memalign(8, f->distWidth*f->distStride*sizeof(int32_t));
+
+ for(y=0; y<vec->length; y++){
+ for(x=0; x<vec->length; x++){
+ double d= vec->coeff[x] * vec->coeff[y];
+
+ f->distCoeff[x + y*f->distStride]= (int)(d*(1<<10) + 0.5);
+// if(y==vec->length/2)
+// printf("%6d ", f->distCoeff[x + y*f->distStride]);
+ }
+ }
+ sws_freeVec(vec);
+
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ int sw, sh;
+//__asm__ volatile("emms\n\t");
+ allocStuff(&vf->priv->luma, width, height);
+
+ getSubSampleFactors(&sw, &sh, outfmt);
+ allocStuff(&vf->priv->chroma, width>>sw, height>>sh);
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void freeBuffers(FilterParam *f){
+ if(f->preFilterContext) sws_freeContext(f->preFilterContext);
+ f->preFilterContext=NULL;
+
+ free(f->preFilterBuf);
+ f->preFilterBuf=NULL;
+
+ free(f->distCoeff);
+ f->distCoeff=NULL;
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ freeBuffers(&vf->priv->luma);
+ freeBuffers(&vf->priv->chroma);
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){
+ int x, y;
+ FilterParam f= *fp;
+ const int radius= f.distWidth/2;
+ const uint8_t* const srcArray[MP_MAX_PLANES] = {src};
+ uint8_t *dstArray[MP_MAX_PLANES]= {f.preFilterBuf};
+ int srcStrideArray[MP_MAX_PLANES]= {srcStride};
+ int dstStrideArray[MP_MAX_PLANES]= {f.preFilterStride};
+
+// f.preFilterContext->swScale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
+ sws_scale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int sum=0;
+ int div=0;
+ int dy;
+ const int preVal= f.preFilterBuf[x + y*f.preFilterStride];
+#if 0
+ const int srcVal= src[x + y*srcStride];
+if((x/32)&1){
+ dst[x + y*dstStride]= srcVal;
+ if(y%32==0) dst[x + y*dstStride]= 0;
+ continue;
+}
+#endif
+ if(x >= radius && x < w - radius){
+ for(dy=0; dy<radius*2+1; dy++){
+ int dx;
+ int iy= y+dy - radius;
+ if (iy<0) iy= -iy;
+ else if(iy>=h) iy= h+h-iy-1;
+
+ for(dx=0; dx<radius*2+1; dx++){
+ const int ix= x+dx - radius;
+ int factor;
+
+ factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
+ *f.distCoeff[dx + dy*f.distStride];
+ sum+= src[ix + iy*srcStride] *factor;
+ div+= factor;
+ }
+ }
+ }else{
+ for(dy=0; dy<radius*2+1; dy++){
+ int dx;
+ int iy= y+dy - radius;
+ if (iy<0) iy= -iy;
+ else if(iy>=h) iy= h+h-iy-1;
+
+ for(dx=0; dx<radius*2+1; dx++){
+ int ix= x+dx - radius;
+ int factor;
+ if (ix<0) ix= -ix;
+ else if(ix>=w) ix= w+w-ix-1;
+
+ factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
+ *f.distCoeff[dx + dy*f.distStride];
+ sum+= src[ix + iy*srcStride] *factor;
+ div+= factor;
+ }
+ }
+ }
+ dst[x + y*dstStride]= (sum + div/2)/div;
+ }
+ }
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+
+ mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->w,mpi->h);
+
+ assert(mpi->flags&MP_IMGFLAG_PLANAR);
+
+ blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma);
+ blur(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
+ blur(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ int e;
+
+ vf->config=config;
+ vf->put_image=put_image;
+// vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if(args==NULL) return 0;
+
+ e=sscanf(args, "%f:%f:%f:%f:%f:%f",
+ &vf->priv->luma.radius,
+ &vf->priv->luma.preFilterRadius,
+ &vf->priv->luma.strength,
+ &vf->priv->chroma.radius,
+ &vf->priv->chroma.preFilterRadius,
+ &vf->priv->chroma.strength
+ );
+
+ vf->priv->luma.quality = vf->priv->chroma.quality= 3.0;
+
+ if(e==3){
+ vf->priv->chroma.radius= vf->priv->luma.radius;
+ vf->priv->chroma.preFilterRadius = vf->priv->luma.preFilterRadius;
+ vf->priv->chroma.strength= vf->priv->luma.strength;
+ }else if(e!=6)
+ return 0;
+
+// if(vf->priv->luma.radius < 0) return 0;
+// if(vf->priv->chroma.radius < 0) return 0;
+
+ return 1;
+}
+
+const vf_info_t vf_info_sab = {
+ "shape adaptive blur",
+ "sab",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_scale.h b/libavfilter/libmpcodecs/vf_scale.h
new file mode 100644
index 0000000000..91ed103c30
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_scale.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_VF_SCALE_H
+#define MPLAYER_VF_SCALE_H
+
+extern int sws_chr_vshift;
+extern int sws_chr_hshift;
+
+extern float sws_chr_gblur;
+extern float sws_lum_gblur;
+extern float sws_chr_sharpen;
+extern float sws_lum_sharpen;
+
+extern int sws_flags;
+
+int get_sws_cpuflags(void);
+struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat);
+
+#endif /* MPLAYER_VF_SCALE_H */
diff --git a/libavfilter/libmpcodecs/vf_screenshot.c b/libavfilter/libmpcodecs/vf_screenshot.c
new file mode 100644
index 0000000000..82b345b446
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_screenshot.c
@@ -0,0 +1,322 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <string.h>
+#include <inttypes.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "vf_scale.h"
+
+#include "libswscale/swscale.h"
+#include "libavcodec/avcodec.h"
+
+struct vf_priv_s {
+ int frameno;
+ char fname[102];
+ /// shot stores current screenshot mode:
+ /// 0: don't take screenshots
+ /// 1: take single screenshot, reset to 0 afterwards
+ /// 2: take screenshots of each frame
+ int shot, store_slices;
+ int dw, dh, stride;
+ uint8_t *buffer;
+ struct SwsContext *ctx;
+ AVCodecContext *avctx;
+ uint8_t *outbuffer;
+ int outbuffer_size;
+};
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ vf->priv->ctx=sws_getContextFromCmdLine(width, height, outfmt,
+ d_width, d_height, IMGFMT_RGB24);
+
+ vf->priv->outbuffer_size = d_width * d_height * 3 * 2;
+ vf->priv->outbuffer = realloc(vf->priv->outbuffer, vf->priv->outbuffer_size);
+ vf->priv->avctx->width = d_width;
+ vf->priv->avctx->height = d_height;
+ vf->priv->avctx->pix_fmt = PIX_FMT_RGB24;
+ vf->priv->avctx->compression_level = 0;
+ vf->priv->dw = d_width;
+ vf->priv->dh = d_height;
+ vf->priv->stride = (3*vf->priv->dw+15)&~15;
+
+ free(vf->priv->buffer); // probably reconfigured
+ vf->priv->buffer = NULL;
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void write_png(struct vf_priv_s *priv)
+{
+ char *fname = priv->fname;
+ FILE * fp;
+ AVFrame pic;
+ int size;
+
+ fp = fopen (fname, "wb");
+ if (fp == NULL) {
+ mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname);
+ return;
+ }
+
+ pic.data[0] = priv->buffer;
+ pic.linesize[0] = priv->stride;
+ size = avcodec_encode_video(priv->avctx, priv->outbuffer, priv->outbuffer_size, &pic);
+ if (size > 0)
+ fwrite(priv->outbuffer, size, 1, fp);
+
+ fclose (fp);
+}
+
+static int fexists(char *fname)
+{
+ struct stat dummy;
+ if (stat(fname, &dummy) == 0) return 1;
+ else return 0;
+}
+
+static void gen_fname(struct vf_priv_s* priv)
+{
+ do {
+ snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno);
+ } while (fexists(priv->fname) && priv->frameno < 100000);
+ if (fexists(priv->fname)) {
+ priv->fname[0] = '\0';
+ return;
+ }
+
+ mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname);
+
+}
+
+static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi)
+{
+ uint8_t *dst[MP_MAX_PLANES] = {NULL};
+ int dst_stride[MP_MAX_PLANES] = {0};
+
+ dst_stride[0] = priv->stride;
+ if (!priv->buffer)
+ priv->buffer = av_malloc(dst_stride[0]*priv->dh);
+
+ dst[0] = priv->buffer;
+ sws_scale(priv->ctx, mpi->planes, mpi->stride, 0, priv->dh, dst, dst_stride);
+}
+
+static void start_slice(struct vf_instance *vf, mp_image_t *mpi)
+{
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags, mpi->width, mpi->height);
+ if (vf->priv->shot) {
+ vf->priv->store_slices = 1;
+ if (!vf->priv->buffer)
+ vf->priv->buffer = av_malloc(vf->priv->stride*vf->priv->dh);
+ }
+
+}
+
+static void draw_slice(struct vf_instance *vf, unsigned char** src,
+ int* stride, int w,int h, int x, int y)
+{
+ if (vf->priv->store_slices) {
+ uint8_t *dst[MP_MAX_PLANES] = {NULL};
+ int dst_stride[MP_MAX_PLANES] = {0};
+ dst_stride[0] = vf->priv->stride;
+ dst[0] = vf->priv->buffer;
+ sws_scale(vf->priv->ctx, src, stride, y, h, dst, dst_stride);
+ }
+ vf_next_draw_slice(vf,src,stride,w,h,x,y);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi)
+{
+ // FIXME: should vf.c really call get_image when using slices??
+ if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
+ return;
+ vf->dmpi= vf_get_image(vf->next, mpi->imgfmt,
+ mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height);
+
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->width=vf->dmpi->width;
+
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+
+ mpi->priv=(void*)vf->dmpi;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi = (mp_image_t *)mpi->priv;
+
+ if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
+ dmpi = vf->dmpi;
+ else
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, 0,
+ mpi->width, mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+ dmpi->planes[0]=mpi->planes[0];
+ dmpi->planes[1]=mpi->planes[1];
+ dmpi->planes[2]=mpi->planes[2];
+ dmpi->stride[0]=mpi->stride[0];
+ dmpi->stride[1]=mpi->stride[1];
+ dmpi->stride[2]=mpi->stride[2];
+ dmpi->width=mpi->width;
+ dmpi->height=mpi->height;
+ }
+
+ if(vf->priv->shot) {
+ if (vf->priv->shot==1)
+ vf->priv->shot=0;
+ gen_fname(vf->priv);
+ if (vf->priv->fname[0]) {
+ if (!vf->priv->store_slices)
+ scale_image(vf->priv, dmpi);
+ write_png(vf->priv);
+ }
+ vf->priv->store_slices = 0;
+ }
+
+ return vf_next_put_image(vf, dmpi, pts);
+}
+
+static int control (vf_instance_t *vf, int request, void *data)
+{
+ /** data contains an integer argument
+ * 0: take screenshot with the next frame
+ * 1: take screenshots with each frame until the same command is given once again
+ **/
+ if(request==VFCTRL_SCREENSHOT) {
+ if (data && *(int*)data) { // repeated screenshot mode
+ if (vf->priv->shot==2)
+ vf->priv->shot=0;
+ else
+ vf->priv->shot=2;
+ } else { // single screenshot
+ if (!vf->priv->shot)
+ vf->priv->shot=1;
+ }
+ return CONTROL_TRUE;
+ }
+ return vf_next_control (vf, request, data);
+}
+
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ switch(fmt){
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_UYVY:
+ case IMGFMT_YUY2:
+ case IMGFMT_BGR32:
+ case IMGFMT_BGR24:
+ case IMGFMT_BGR16:
+ case IMGFMT_BGR15:
+ case IMGFMT_BGR12:
+ case IMGFMT_RGB32:
+ case IMGFMT_RGB24:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static void uninit(vf_instance_t *vf)
+{
+ avcodec_close(vf->priv->avctx);
+ av_freep(&vf->priv->avctx);
+ if(vf->priv->ctx) sws_freeContext(vf->priv->ctx);
+ av_free(vf->priv->buffer);
+ free(vf->priv->outbuffer);
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->config=config;
+ vf->control=control;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->start_slice=start_slice;
+ vf->draw_slice=draw_slice;
+ vf->get_image=get_image;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ vf->priv->frameno=0;
+ vf->priv->shot=0;
+ vf->priv->store_slices=0;
+ vf->priv->buffer=0;
+ vf->priv->outbuffer=0;
+ vf->priv->ctx=0;
+ vf->priv->avctx = avcodec_alloc_context();
+ avcodec_register_all();
+ if (avcodec_open(vf->priv->avctx, avcodec_find_encoder(CODEC_ID_PNG))) {
+ mp_msg(MSGT_VFILTER, MSGL_FATAL, "Could not open libavcodec PNG encoder\n");
+ return 0;
+ }
+ return 1;
+}
+
+
+const vf_info_t vf_info_screenshot = {
+ "screenshot to file",
+ "screenshot",
+ "A'rpi, Jindrich Makovicka",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_smartblur.c b/libavfilter/libmpcodecs/vf_smartblur.c
new file mode 100644
index 0000000000..3e20880f04
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_smartblur.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "mp_msg.h"
+#include "libavutil/avutil.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libswscale/swscale.h"
+#include "vf_scale.h"
+
+//===========================================================================//
+
+typedef struct FilterParam{
+ float radius;
+ float strength;
+ int threshold;
+ float quality;
+ struct SwsContext *filterContext;
+}FilterParam;
+
+struct vf_priv_s {
+ FilterParam luma;
+ FilterParam chroma;
+};
+
+
+/***************************************************************************/
+
+//FIXME stupid code duplication
+static void getSubSampleFactors(int *h, int *v, int format){
+ switch(format){
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ *h=1;
+ *v=1;
+ break;
+ case IMGFMT_YVU9:
+ *h=2;
+ *v=2;
+ break;
+ case IMGFMT_444P:
+ *h=0;
+ *v=0;
+ break;
+ case IMGFMT_422P:
+ *h=1;
+ *v=0;
+ break;
+ case IMGFMT_411P:
+ *h=2;
+ *v=0;
+ break;
+ }
+}
+
+static int allocStuff(FilterParam *f, int width, int height){
+ SwsVector *vec;
+ SwsFilter swsF;
+
+ vec = sws_getGaussianVec(f->radius, f->quality);
+ sws_scaleVec(vec, f->strength);
+ vec->coeff[vec->length/2]+= 1.0 - f->strength;
+ swsF.lumH= swsF.lumV= vec;
+ swsF.chrH= swsF.chrV= NULL;
+ f->filterContext= sws_getContext(
+ width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, SWS_BICUBIC | get_sws_cpuflags(), &swsF, NULL, NULL);
+
+ sws_freeVec(vec);
+
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ int sw, sh;
+
+ allocStuff(&vf->priv->luma, width, height);
+
+ getSubSampleFactors(&sw, &sh, outfmt);
+ allocStuff(&vf->priv->chroma, width>>sw, height>>sh);
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void freeBuffers(FilterParam *f){
+ if(f->filterContext) sws_freeContext(f->filterContext);
+ f->filterContext=NULL;
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ freeBuffers(&vf->priv->luma);
+ freeBuffers(&vf->priv->chroma);
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){
+ int x, y;
+ FilterParam f= *fp;
+ const uint8_t* const srcArray[MP_MAX_PLANES] = {src};
+ uint8_t *dstArray[MP_MAX_PLANES]= {dst};
+ int srcStrideArray[MP_MAX_PLANES]= {srcStride};
+ int dstStrideArray[MP_MAX_PLANES]= {dstStride};
+
+ sws_scale(f.filterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
+
+ if(f.threshold > 0){
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ const int orig= src[x + y*srcStride];
+ const int filtered= dst[x + y*dstStride];
+ const int diff= orig - filtered;
+
+ if(diff > 0){
+ if(diff > 2*f.threshold){
+ dst[x + y*dstStride]= orig;
+ }else if(diff > f.threshold){
+ dst[x + y*dstStride]= filtered + diff - f.threshold;
+ }
+ }else{
+ if(-diff > 2*f.threshold){
+ dst[x + y*dstStride]= orig;
+ }else if(-diff > f.threshold){
+ dst[x + y*dstStride]= filtered + diff + f.threshold;
+ }
+ }
+ }
+ }
+ }else if(f.threshold < 0){
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ const int orig= src[x + y*srcStride];
+ const int filtered= dst[x + y*dstStride];
+ const int diff= orig - filtered;
+
+ if(diff > 0){
+ if(diff > -2*f.threshold){
+ }else if(diff > -f.threshold){
+ dst[x + y*dstStride]= orig - diff - f.threshold;
+ }else
+ dst[x + y*dstStride]= orig;
+ }else{
+ if(diff < 2*f.threshold){
+ }else if(diff < f.threshold){
+ dst[x + y*dstStride]= orig - diff + f.threshold;
+ }else
+ dst[x + y*dstStride]= orig;
+ }
+ }
+ }
+ }
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int cw= mpi->w >> mpi->chroma_x_shift;
+ int ch= mpi->h >> mpi->chroma_y_shift;
+ FilterParam *f= &vf->priv;
+
+ mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE|
+ (f->threshold) ? MP_IMGFLAG_READABLE : 0,
+ mpi->w,mpi->h);
+
+ assert(mpi->flags&MP_IMGFLAG_PLANAR);
+
+ blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma);
+ blur(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
+ blur(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ int e;
+
+ vf->config=config;
+ vf->put_image=put_image;
+// vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ if(args==NULL) return 0;
+
+ e=sscanf(args, "%f:%f:%d:%f:%f:%d",
+ &vf->priv->luma.radius,
+ &vf->priv->luma.strength,
+ &vf->priv->luma.threshold,
+ &vf->priv->chroma.radius,
+ &vf->priv->chroma.strength,
+ &vf->priv->chroma.threshold
+ );
+
+ vf->priv->luma.quality = vf->priv->chroma.quality= 3.0;
+
+ if(e==3){
+ vf->priv->chroma.radius= vf->priv->luma.radius;
+ vf->priv->chroma.strength= vf->priv->luma.strength;
+ vf->priv->chroma.threshold = vf->priv->luma.threshold;
+ }else if(e!=6)
+ return 0;
+
+ return 1;
+}
+
+const vf_info_t vf_info_smartblur = {
+ "smart blur",
+ "smartblur",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_softpulldown.c b/libavfilter/libmpcodecs/vf_softpulldown.c
new file mode 100644
index 0000000000..04d1eae3d4
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_softpulldown.c
@@ -0,0 +1,164 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+struct vf_priv_s {
+ int state;
+ long long in;
+ long long out;
+};
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+ int ret = 0;
+ int flags = mpi->fields;
+ int state = vf->priv->state;
+
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
+
+ vf->priv->in++;
+
+ if ((state == 0 &&
+ !(flags & MP_IMGFIELD_TOP_FIRST)) ||
+ (state == 1 &&
+ flags & MP_IMGFIELD_TOP_FIRST)) {
+ mp_msg(MSGT_VFILTER, MSGL_WARN,
+ "softpulldown: Unexpected field flags: state=%d top_field_first=%d repeat_first_field=%d\n",
+ state,
+ (flags & MP_IMGFIELD_TOP_FIRST) != 0,
+ (flags & MP_IMGFIELD_REPEAT_FIRST) != 0);
+ state ^= 1;
+ }
+
+ if (state == 0) {
+ ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
+ vf->priv->out++;
+ if (flags & MP_IMGFIELD_REPEAT_FIRST) {
+ my_memcpy_pic(dmpi->planes[0],
+ mpi->planes[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1],
+ mpi->planes[1],
+ mpi->chroma_width,
+ mpi->chroma_height/2,
+ dmpi->stride[1]*2,
+ mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2],
+ mpi->planes[2],
+ mpi->chroma_width,
+ mpi->chroma_height/2,
+ dmpi->stride[2]*2,
+ mpi->stride[2]*2);
+ }
+ state=1;
+ }
+ } else {
+ my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
+ mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
+ mpi->planes[1]+mpi->stride[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
+ mpi->planes[2]+mpi->stride[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ vf->priv->out++;
+ if (flags & MP_IMGFIELD_REPEAT_FIRST) {
+ ret |= vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
+ vf->priv->out++;
+ state=0;
+ } else {
+ my_memcpy_pic(dmpi->planes[0],
+ mpi->planes[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1],
+ mpi->planes[1],
+ mpi->chroma_width,
+ mpi->chroma_height/2,
+ dmpi->stride[1]*2,
+ mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2],
+ mpi->planes[2],
+ mpi->chroma_width,
+ mpi->chroma_height/2,
+ dmpi->stride[2]*2,
+ mpi->stride[2]*2);
+ }
+ }
+ }
+
+ vf->priv->state = state;
+
+ return ret;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ mp_msg(MSGT_VFILTER, MSGL_INFO, "softpulldown: %lld frames in, %lld frames out\n", vf->priv->in, vf->priv->out);
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ vf->config = config;
+ vf->put_image = put_image;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ vf->priv->state = 0;
+ return 1;
+}
+
+const vf_info_t vf_info_softpulldown = {
+ "mpeg2 soft 3:2 pulldown",
+ "softpulldown",
+ "Tobias Diedrich <ranma+mplayer@tdiedrich.de>",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_softskip.c b/libavfilter/libmpcodecs/vf_softskip.c
new file mode 100644
index 0000000000..150c3e7b72
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_softskip.c
@@ -0,0 +1,102 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ int skipflag;
+};
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+
+ if (vf->priv->skipflag)
+ return vf->priv->skipflag = 0;
+
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_EXPORT, 0, mpi->width, mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ dmpi->planes[0] = mpi->planes[0];
+ dmpi->stride[0] = mpi->stride[0];
+ if (dmpi->flags&MP_IMGFLAG_PLANAR) {
+ dmpi->planes[1] = mpi->planes[1];
+ dmpi->stride[1] = mpi->stride[1];
+ dmpi->planes[2] = mpi->planes[2];
+ dmpi->stride[2] = mpi->stride[2];
+ }
+
+ return vf_next_put_image(vf, dmpi, pts);
+}
+
+static int control(struct vf_instance *vf, int request, void* data)
+{
+ switch (request) {
+ case VFCTRL_SKIP_NEXT_FRAME:
+ vf->priv->skipflag = 1;
+ return CONTROL_TRUE;
+ }
+ return vf_next_control(vf, request, data);
+}
+
+#if 0
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - figure out which other formats work */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+#endif
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ vf->put_image = put_image;
+ vf->control = control;
+ vf->uninit = uninit;
+ vf->priv = calloc(1, sizeof(struct vf_priv_s));
+ return 1;
+}
+
+const vf_info_t vf_info_softskip = {
+ "soft (post-filter) frame skipping for encoding",
+ "softskip",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_spp.c b/libavfilter/libmpcodecs/vf_spp.c
new file mode 100644
index 0000000000..0b4b2306f4
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_spp.c
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * This implementation is based on an algorithm described in
+ * "Aria Nosratinia Embedded Post-Processing for
+ * Enhancement of Compressed Images (1999)"
+ * (http://citeseer.nj.nec.com/nosratinia99embedded.html)
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavcodec/avcodec.h"
+#include "libavcodec/dsputil.h"
+
+#undef fprintf
+#undef free
+#undef malloc
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "vd_ffmpeg.h"
+#include "libvo/fastmemcpy.h"
+
+#define XMIN(a,b) ((a) < (b) ? (a) : (b))
+
+//===========================================================================//
+static const uint8_t __attribute__((aligned(8))) dither[8][8]={
+{ 0, 48, 12, 60, 3, 51, 15, 63, },
+{ 32, 16, 44, 28, 35, 19, 47, 31, },
+{ 8, 56, 4, 52, 11, 59, 7, 55, },
+{ 40, 24, 36, 20, 43, 27, 39, 23, },
+{ 2, 50, 14, 62, 1, 49, 13, 61, },
+{ 34, 18, 46, 30, 33, 17, 45, 29, },
+{ 10, 58, 6, 54, 9, 57, 5, 53, },
+{ 42, 26, 38, 22, 41, 25, 37, 21, },
+};
+
+static const uint8_t offset[127][2]= {
+{0,0},
+{0,0}, {4,4},
+{0,0}, {2,2}, {6,4}, {4,6},
+{0,0}, {5,1}, {2,2}, {7,3}, {4,4}, {1,5}, {6,6}, {3,7},
+
+{0,0}, {4,0}, {1,1}, {5,1}, {3,2}, {7,2}, {2,3}, {6,3},
+{0,4}, {4,4}, {1,5}, {5,5}, {3,6}, {7,6}, {2,7}, {6,7},
+
+{0,0}, {0,2}, {0,4}, {0,6}, {1,1}, {1,3}, {1,5}, {1,7},
+{2,0}, {2,2}, {2,4}, {2,6}, {3,1}, {3,3}, {3,5}, {3,7},
+{4,0}, {4,2}, {4,4}, {4,6}, {5,1}, {5,3}, {5,5}, {5,7},
+{6,0}, {6,2}, {6,4}, {6,6}, {7,1}, {7,3}, {7,5}, {7,7},
+
+{0,0}, {4,4}, {0,4}, {4,0}, {2,2}, {6,6}, {2,6}, {6,2},
+{0,2}, {4,6}, {0,6}, {4,2}, {2,0}, {6,4}, {2,4}, {6,0},
+{1,1}, {5,5}, {1,5}, {5,1}, {3,3}, {7,7}, {3,7}, {7,3},
+{1,3}, {5,7}, {1,7}, {5,3}, {3,1}, {7,5}, {3,5}, {7,1},
+{0,1}, {4,5}, {0,5}, {4,1}, {2,3}, {6,7}, {2,7}, {6,3},
+{0,3}, {4,7}, {0,7}, {4,3}, {2,1}, {6,5}, {2,5}, {6,1},
+{1,0}, {5,4}, {1,4}, {5,0}, {3,2}, {7,6}, {3,6}, {7,2},
+{1,2}, {5,6}, {1,6}, {5,2}, {3,0}, {7,4}, {3,4}, {7,0},
+};
+
+struct vf_priv_s {
+ int log2_count;
+ int qp;
+ int mode;
+ int mpeg2;
+ int temp_stride;
+ uint8_t *src;
+ int16_t *temp;
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ char *non_b_qp;
+};
+
+#define SHIFT 22
+
+static void hardthresh_c(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
+ int i;
+ int bias= 0; //FIXME
+ unsigned int threshold1, threshold2;
+
+ threshold1= qp*((1<<4) - bias) - 1;
+ threshold2= (threshold1<<1);
+
+ memset(dst, 0, 64*sizeof(DCTELEM));
+ dst[0]= (src[0] + 4)>>3;
+
+ for(i=1; i<64; i++){
+ int level= src[i];
+ if(((unsigned)(level+threshold1))>threshold2){
+ const int j= permutation[i];
+ dst[j]= (level + 4)>>3;
+ }
+ }
+}
+
+static void softthresh_c(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
+ int i;
+ int bias= 0; //FIXME
+ unsigned int threshold1, threshold2;
+
+ threshold1= qp*((1<<4) - bias) - 1;
+ threshold2= (threshold1<<1);
+
+ memset(dst, 0, 64*sizeof(DCTELEM));
+ dst[0]= (src[0] + 4)>>3;
+
+ for(i=1; i<64; i++){
+ int level= src[i];
+ if(((unsigned)(level+threshold1))>threshold2){
+ const int j= permutation[i];
+ if(level>0)
+ dst[j]= (level - threshold1 + 4)>>3;
+ else
+ dst[j]= (level + threshold1 + 4)>>3;
+ }
+ }
+}
+
+#if HAVE_MMX
+static void hardthresh_mmx(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
+ int bias= 0; //FIXME
+ unsigned int threshold1;
+
+ threshold1= qp*((1<<4) - bias) - 1;
+
+ __asm__ volatile(
+#define REQUANT_CORE(dst0, dst1, dst2, dst3, src0, src1, src2, src3) \
+ "movq " #src0 ", %%mm0 \n\t"\
+ "movq " #src1 ", %%mm1 \n\t"\
+ "movq " #src2 ", %%mm2 \n\t"\
+ "movq " #src3 ", %%mm3 \n\t"\
+ "psubw %%mm4, %%mm0 \n\t"\
+ "psubw %%mm4, %%mm1 \n\t"\
+ "psubw %%mm4, %%mm2 \n\t"\
+ "psubw %%mm4, %%mm3 \n\t"\
+ "paddusw %%mm5, %%mm0 \n\t"\
+ "paddusw %%mm5, %%mm1 \n\t"\
+ "paddusw %%mm5, %%mm2 \n\t"\
+ "paddusw %%mm5, %%mm3 \n\t"\
+ "paddw %%mm6, %%mm0 \n\t"\
+ "paddw %%mm6, %%mm1 \n\t"\
+ "paddw %%mm6, %%mm2 \n\t"\
+ "paddw %%mm6, %%mm3 \n\t"\
+ "psubusw %%mm6, %%mm0 \n\t"\
+ "psubusw %%mm6, %%mm1 \n\t"\
+ "psubusw %%mm6, %%mm2 \n\t"\
+ "psubusw %%mm6, %%mm3 \n\t"\
+ "psraw $3, %%mm0 \n\t"\
+ "psraw $3, %%mm1 \n\t"\
+ "psraw $3, %%mm2 \n\t"\
+ "psraw $3, %%mm3 \n\t"\
+\
+ "movq %%mm0, %%mm7 \n\t"\
+ "punpcklwd %%mm2, %%mm0 \n\t" /*A*/\
+ "punpckhwd %%mm2, %%mm7 \n\t" /*C*/\
+ "movq %%mm1, %%mm2 \n\t"\
+ "punpcklwd %%mm3, %%mm1 \n\t" /*B*/\
+ "punpckhwd %%mm3, %%mm2 \n\t" /*D*/\
+ "movq %%mm0, %%mm3 \n\t"\
+ "punpcklwd %%mm1, %%mm0 \n\t" /*A*/\
+ "punpckhwd %%mm7, %%mm3 \n\t" /*C*/\
+ "punpcklwd %%mm2, %%mm7 \n\t" /*B*/\
+ "punpckhwd %%mm2, %%mm1 \n\t" /*D*/\
+\
+ "movq %%mm0, " #dst0 " \n\t"\
+ "movq %%mm7, " #dst1 " \n\t"\
+ "movq %%mm3, " #dst2 " \n\t"\
+ "movq %%mm1, " #dst3 " \n\t"
+
+ "movd %2, %%mm4 \n\t"
+ "movd %3, %%mm5 \n\t"
+ "movd %4, %%mm6 \n\t"
+ "packssdw %%mm4, %%mm4 \n\t"
+ "packssdw %%mm5, %%mm5 \n\t"
+ "packssdw %%mm6, %%mm6 \n\t"
+ "packssdw %%mm4, %%mm4 \n\t"
+ "packssdw %%mm5, %%mm5 \n\t"
+ "packssdw %%mm6, %%mm6 \n\t"
+ REQUANT_CORE( (%1), 8(%1), 16(%1), 24(%1), (%0), 8(%0), 64(%0), 72(%0))
+ REQUANT_CORE(32(%1), 40(%1), 48(%1), 56(%1),16(%0),24(%0), 48(%0), 56(%0))
+ REQUANT_CORE(64(%1), 72(%1), 80(%1), 88(%1),32(%0),40(%0), 96(%0),104(%0))
+ REQUANT_CORE(96(%1),104(%1),112(%1),120(%1),80(%0),88(%0),112(%0),120(%0))
+ : : "r" (src), "r" (dst), "g" (threshold1+1), "g" (threshold1+5), "g" (threshold1-4) //FIXME maybe more accurate then needed?
+ );
+ dst[0]= (src[0] + 4)>>3;
+}
+
+static void softthresh_mmx(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation){
+ int bias= 0; //FIXME
+ unsigned int threshold1;
+
+ threshold1= qp*((1<<4) - bias) - 1;
+
+ __asm__ volatile(
+#undef REQUANT_CORE
+#define REQUANT_CORE(dst0, dst1, dst2, dst3, src0, src1, src2, src3) \
+ "movq " #src0 ", %%mm0 \n\t"\
+ "movq " #src1 ", %%mm1 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "pcmpgtw %%mm0, %%mm6 \n\t"\
+ "pcmpgtw %%mm1, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm0 \n\t"\
+ "pxor %%mm7, %%mm1 \n\t"\
+ "psubusw %%mm4, %%mm0 \n\t"\
+ "psubusw %%mm4, %%mm1 \n\t"\
+ "pxor %%mm6, %%mm0 \n\t"\
+ "pxor %%mm7, %%mm1 \n\t"\
+ "movq " #src2 ", %%mm2 \n\t"\
+ "movq " #src3 ", %%mm3 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "pcmpgtw %%mm2, %%mm6 \n\t"\
+ "pcmpgtw %%mm3, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm2 \n\t"\
+ "pxor %%mm7, %%mm3 \n\t"\
+ "psubusw %%mm4, %%mm2 \n\t"\
+ "psubusw %%mm4, %%mm3 \n\t"\
+ "pxor %%mm6, %%mm2 \n\t"\
+ "pxor %%mm7, %%mm3 \n\t"\
+\
+ "paddsw %%mm5, %%mm0 \n\t"\
+ "paddsw %%mm5, %%mm1 \n\t"\
+ "paddsw %%mm5, %%mm2 \n\t"\
+ "paddsw %%mm5, %%mm3 \n\t"\
+ "psraw $3, %%mm0 \n\t"\
+ "psraw $3, %%mm1 \n\t"\
+ "psraw $3, %%mm2 \n\t"\
+ "psraw $3, %%mm3 \n\t"\
+\
+ "movq %%mm0, %%mm7 \n\t"\
+ "punpcklwd %%mm2, %%mm0 \n\t" /*A*/\
+ "punpckhwd %%mm2, %%mm7 \n\t" /*C*/\
+ "movq %%mm1, %%mm2 \n\t"\
+ "punpcklwd %%mm3, %%mm1 \n\t" /*B*/\
+ "punpckhwd %%mm3, %%mm2 \n\t" /*D*/\
+ "movq %%mm0, %%mm3 \n\t"\
+ "punpcklwd %%mm1, %%mm0 \n\t" /*A*/\
+ "punpckhwd %%mm7, %%mm3 \n\t" /*C*/\
+ "punpcklwd %%mm2, %%mm7 \n\t" /*B*/\
+ "punpckhwd %%mm2, %%mm1 \n\t" /*D*/\
+\
+ "movq %%mm0, " #dst0 " \n\t"\
+ "movq %%mm7, " #dst1 " \n\t"\
+ "movq %%mm3, " #dst2 " \n\t"\
+ "movq %%mm1, " #dst3 " \n\t"
+
+ "movd %2, %%mm4 \n\t"
+ "movd %3, %%mm5 \n\t"
+ "packssdw %%mm4, %%mm4 \n\t"
+ "packssdw %%mm5, %%mm5 \n\t"
+ "packssdw %%mm4, %%mm4 \n\t"
+ "packssdw %%mm5, %%mm5 \n\t"
+ REQUANT_CORE( (%1), 8(%1), 16(%1), 24(%1), (%0), 8(%0), 64(%0), 72(%0))
+ REQUANT_CORE(32(%1), 40(%1), 48(%1), 56(%1),16(%0),24(%0), 48(%0), 56(%0))
+ REQUANT_CORE(64(%1), 72(%1), 80(%1), 88(%1),32(%0),40(%0), 96(%0),104(%0))
+ REQUANT_CORE(96(%1),104(%1),112(%1),120(%1),80(%0),88(%0),112(%0),120(%0))
+ : : "r" (src), "r" (dst), "g" (threshold1), "rm" (4) //FIXME maybe more accurate then needed?
+ );
+
+ dst[0]= (src[0] + 4)>>3;
+}
+#endif
+
+static inline void add_block(int16_t *dst, int stride, DCTELEM block[64]){
+ int y;
+
+ for(y=0; y<8; y++){
+ *(uint32_t*)&dst[0 + y*stride]+= *(uint32_t*)&block[0 + y*8];
+ *(uint32_t*)&dst[2 + y*stride]+= *(uint32_t*)&block[2 + y*8];
+ *(uint32_t*)&dst[4 + y*stride]+= *(uint32_t*)&block[4 + y*8];
+ *(uint32_t*)&dst[6 + y*stride]+= *(uint32_t*)&block[6 + y*8];
+ }
+}
+
+static void store_slice_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale){
+ int y, x;
+
+#define STORE(pos) \
+ temp= ((src[x + y*src_stride + pos]<<log2_scale) + d[pos])>>6;\
+ if(temp & 0x100) temp= ~(temp>>31);\
+ dst[x + y*dst_stride + pos]= temp;
+
+ for(y=0; y<height; y++){
+ const uint8_t *d= dither[y];
+ for(x=0; x<width; x+=8){
+ int temp;
+ STORE(0);
+ STORE(1);
+ STORE(2);
+ STORE(3);
+ STORE(4);
+ STORE(5);
+ STORE(6);
+ STORE(7);
+ }
+ }
+}
+
+#if HAVE_MMX
+static void store_slice_mmx(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale){
+ int y;
+
+ for(y=0; y<height; y++){
+ uint8_t *dst1= dst;
+ int16_t *src1= src;
+ __asm__ volatile(
+ "movq (%3), %%mm3 \n\t"
+ "movq (%3), %%mm4 \n\t"
+ "movd %4, %%mm2 \n\t"
+ "pxor %%mm0, %%mm0 \n\t"
+ "punpcklbw %%mm0, %%mm3 \n\t"
+ "punpckhbw %%mm0, %%mm4 \n\t"
+ "psraw %%mm2, %%mm3 \n\t"
+ "psraw %%mm2, %%mm4 \n\t"
+ "movd %5, %%mm2 \n\t"
+ "1: \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "movq 8(%0), %%mm1 \n\t"
+ "paddw %%mm3, %%mm0 \n\t"
+ "paddw %%mm4, %%mm1 \n\t"
+ "psraw %%mm2, %%mm0 \n\t"
+ "psraw %%mm2, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, (%1) \n\t"
+ "add $16, %0 \n\t"
+ "add $8, %1 \n\t"
+ "cmp %2, %1 \n\t"
+ " jb 1b \n\t"
+ : "+r" (src1), "+r"(dst1)
+ : "r"(dst + width), "r"(dither[y]), "g"(log2_scale), "g"(6-log2_scale)
+ );
+ src += src_stride;
+ dst += dst_stride;
+ }
+// if(width != mmxw)
+// store_slice_c(dst + mmxw, src + mmxw, dst_stride, src_stride, width - mmxw, log2_scale);
+}
+#endif
+
+static void (*store_slice)(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)= store_slice_c;
+
+static void (*requantize)(DCTELEM dst[64], DCTELEM src[64], int qp, uint8_t *permutation)= hardthresh_c;
+
+static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, uint8_t *qp_store, int qp_stride, int is_luma){
+ int x, y, i;
+ const int count= 1<<p->log2_count;
+ const int stride= is_luma ? p->temp_stride : ((width+16+15)&(~15));
+ uint64_t __attribute__((aligned(16))) block_align[32];
+ DCTELEM *block = (DCTELEM *)block_align;
+ DCTELEM *block2= (DCTELEM *)(block_align+16);
+
+ if (!src || !dst) return; // HACK avoid crash for Y8 colourspace
+ for(y=0; y<height; y++){
+ int index= 8 + 8*stride + y*stride;
+ fast_memcpy(p->src + index, src + y*src_stride, width);
+ for(x=0; x<8; x++){
+ p->src[index - x - 1]= p->src[index + x ];
+ p->src[index + width + x ]= p->src[index + width - x - 1];
+ }
+ }
+ for(y=0; y<8; y++){
+ fast_memcpy(p->src + ( 7-y)*stride, p->src + ( y+8)*stride, stride);
+ fast_memcpy(p->src + (height+8+y)*stride, p->src + (height-y+7)*stride, stride);
+ }
+ //FIXME (try edge emu)
+
+ for(y=0; y<height+8; y+=8){
+ memset(p->temp + (8+y)*stride, 0, 8*stride*sizeof(int16_t));
+ for(x=0; x<width+8; x+=8){
+ const int qps= 3 + is_luma;
+ int qp;
+
+ if(p->qp)
+ qp= p->qp;
+ else{
+ qp= qp_store[ (XMIN(x, width-1)>>qps) + (XMIN(y, height-1)>>qps) * qp_stride];
+ qp = FFMAX(1, norm_qscale(qp, p->mpeg2));
+ }
+ for(i=0; i<count; i++){
+ const int x1= x + offset[i+count-1][0];
+ const int y1= y + offset[i+count-1][1];
+ const int index= x1 + y1*stride;
+ p->dsp.get_pixels(block, p->src + index, stride);
+ p->dsp.fdct(block);
+ requantize(block2, block, qp, p->dsp.idct_permutation);
+ p->dsp.idct(block2);
+ add_block(p->temp + index, stride, block2);
+ }
+ }
+ if(y)
+ store_slice(dst + (y-8)*dst_stride, p->temp + 8 + y*stride, dst_stride, stride, width, XMIN(8, height+8-y), 6-p->log2_count);
+ }
+#if 0
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ if((((x>>6) ^ (y>>6)) & 1) == 0)
+ dst[x + y*dst_stride]= p->src[8 + 8*stride + x + y*stride];
+ if((x&63) == 0 || (y&63)==0)
+ dst[x + y*dst_stride] += 128;
+ }
+ }
+#endif
+ //FIXME reorder for better caching
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ int h= (height+16+15)&(~15);
+
+ vf->priv->temp_stride= (width+16+15)&(~15);
+ vf->priv->temp= malloc(vf->priv->temp_stride*h*sizeof(int16_t));
+ vf->priv->src = malloc(vf->priv->temp_stride*h*sizeof(uint8_t));
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->width,mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+ }else{
+ dmpi=vf->dmpi;
+ }
+
+ vf->priv->mpeg2= mpi->qscale_type;
+ if(mpi->pict_type != 3 && mpi->qscale && !vf->priv->qp){
+ int w = mpi->qstride;
+ int h = (mpi->h + 15) >> 4;
+ if (!w) {
+ w = (mpi->w + 15) >> 4;
+ h = 1;
+ }
+ if(!vf->priv->non_b_qp)
+ vf->priv->non_b_qp= malloc(w*h);
+ fast_memcpy(vf->priv->non_b_qp, mpi->qscale, w*h);
+ }
+ if(vf->priv->log2_count || !(mpi->flags&MP_IMGFLAG_DIRECT)){
+ char *qp_tab= vf->priv->non_b_qp;
+ if((vf->priv->mode&4) || !qp_tab)
+ qp_tab= mpi->qscale;
+
+ if(qp_tab || vf->priv->qp){
+ filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, qp_tab, mpi->qstride, 1);
+ filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
+ filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, qp_tab, mpi->qstride, 0);
+ }else{
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
+ memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
+ }
+ }
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
+#endif
+#if HAVE_MMX2
+ if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
+#endif
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ if(!vf->priv) return;
+
+ free(vf->priv->temp);
+ vf->priv->temp= NULL;
+ free(vf->priv->src);
+ vf->priv->src= NULL;
+ free(vf->priv->avctx);
+ vf->priv->avctx= NULL;
+ free(vf->priv->non_b_qp);
+ vf->priv->non_b_qp= NULL;
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt){
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_CLPL:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+static int control(struct vf_instance *vf, int request, void* data){
+ switch(request){
+ case VFCTRL_QUERY_MAX_PP_LEVEL:
+ return 6;
+ case VFCTRL_SET_PP_LEVEL:
+ vf->priv->log2_count= *((unsigned int*)data);
+ return CONTROL_TRUE;
+ }
+ return vf_next_control(vf,request,data);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+
+ int log2c=-1;
+
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->control= control;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ init_avcodec();
+
+ vf->priv->avctx= avcodec_alloc_context();
+ dsputil_init(&vf->priv->dsp, vf->priv->avctx);
+
+ vf->priv->log2_count= 3;
+
+ if (args) sscanf(args, "%d:%d:%d", &log2c, &vf->priv->qp, &vf->priv->mode);
+
+ if( log2c >=0 && log2c <=6 )
+ vf->priv->log2_count = log2c;
+
+ if(vf->priv->qp < 0)
+ vf->priv->qp = 0;
+
+ switch(vf->priv->mode&3){
+ default:
+ case 0: requantize= hardthresh_c; break;
+ case 1: requantize= softthresh_c; break;
+ }
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX){
+ store_slice= store_slice_mmx;
+ switch(vf->priv->mode&3){
+ case 0: requantize= hardthresh_mmx; break;
+ case 1: requantize= softthresh_mmx; break;
+ }
+ }
+#endif
+
+ return 1;
+}
+
+const vf_info_t vf_info_spp = {
+ "simple postprocess",
+ "spp",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_swapuv.c b/libavfilter/libmpcodecs/vf_swapuv.c
new file mode 100644
index 0000000000..4d0e8fcb16
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_swapuv.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "mp_msg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+
+//===========================================================================//
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ mp_image_t *dmpi= vf_get_image(vf->next, mpi->imgfmt,
+ mpi->type, mpi->flags, mpi->w, mpi->h);
+
+ mpi->planes[0]=dmpi->planes[0];
+ mpi->planes[1]=dmpi->planes[2];
+ mpi->planes[2]=dmpi->planes[1];
+ mpi->stride[0]=dmpi->stride[0];
+ mpi->stride[1]=dmpi->stride[2];
+ mpi->stride[2]=dmpi->stride[1];
+ mpi->width=dmpi->width;
+
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+ mpi->priv=(void*)dmpi;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(mpi->flags&MP_IMGFLAG_DIRECT){
+ dmpi=(mp_image_t*)mpi->priv;
+ } else {
+ dmpi=vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h);
+ assert(mpi->flags&MP_IMGFLAG_PLANAR);
+ dmpi->planes[0]=mpi->planes[0];
+ dmpi->planes[1]=mpi->planes[2];
+ dmpi->planes[2]=mpi->planes[1];
+ dmpi->stride[0]=mpi->stride[0];
+ dmpi->stride[1]=mpi->stride[2];
+ dmpi->stride[2]=mpi->stride[1];
+ dmpi->width=mpi->width;
+ }
+
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt)
+ {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ return 1;
+}
+
+const vf_info_t vf_info_swapuv = {
+ "UV swapper",
+ "swapuv",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_telecine.c b/libavfilter/libmpcodecs/vf_telecine.c
new file mode 100644
index 0000000000..3b92518c84
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_telecine.c
@@ -0,0 +1,155 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+struct vf_priv_s {
+ int frame;
+};
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+ int ret;
+
+ vf->priv->frame = (vf->priv->frame+1)%4;
+
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
+
+ ret = 0;
+ // 0/0 1/1 2/2 2/3 3/0
+ switch (vf->priv->frame) {
+ case 0:
+ my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
+ mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
+ mpi->planes[1]+mpi->stride[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
+ mpi->planes[2]+mpi->stride[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ case 1:
+ case 2:
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0], mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2], mpi->stride[2]);
+ }
+ return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) || ret;
+ case 3:
+ my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
+ mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
+ mpi->planes[1]+mpi->stride[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
+ mpi->planes[2]+mpi->stride[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ return ret;
+ }
+ return 0;
+}
+
+#if 0
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - figure out which other formats work */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+#endif
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ //vf->config = config;
+ vf->put_image = put_image;
+ //vf->query_format = query_format;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = calloc(1, sizeof(struct vf_priv_s));
+ vf->priv->frame = 1;
+ if (args) sscanf(args, "%d", &vf->priv->frame);
+ vf->priv->frame--;
+ return 1;
+}
+
+const vf_info_t vf_info_telecine = {
+ "telecine filter",
+ "telecine",
+ "Rich Felker",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_test.c b/libavfilter/libmpcodecs/vf_test.c
new file mode 100644
index 0000000000..bef06120e1
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_test.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+//===========================================================================//
+
+#include <inttypes.h>
+#include <math.h>
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define ABS(a,b) ((a) > 0 ? (a) : -(a))
+
+#define WIDTH 512
+#define HEIGHT 512
+
+struct vf_priv_s {
+ int frame_num;
+};
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ if(vf_next_query_format(vf,IMGFMT_YV12)<=0){
+ mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_WarnNextFilterDoesntSupport, "YV12");
+ return 0;
+ }
+
+ //hmm whats the meaning of these ... ;)
+ d_width= width= WIDTH;
+ d_height= height= HEIGHT;
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,IMGFMT_YV12);
+}
+
+static double c[64];
+
+static void initIdct(void)
+{
+ int i;
+
+ for (i=0; i<8; i++)
+ {
+ double s= i==0 ? sqrt(0.125) : 0.5;
+ int j;
+
+ for(j=0; j<8; j++)
+ c[i*8+j]= s*cos((3.141592654/8.0)*i*(j+0.5));
+ }
+}
+
+
+static void idct(uint8_t *dst, int dstStride, int src[64])
+{
+ int i, j, k;
+ double tmp[64];
+
+ for(i=0; i<8; i++)
+ {
+ for(j=0; j<8; j++)
+ {
+ double sum= 0.0;
+
+ for(k=0; k<8; k++)
+ sum+= c[k*8+j]*src[8*i+k];
+
+ tmp[8*i+j]= sum;
+ }
+ }
+
+ for(j=0; j<8; j++)
+ {
+ for(i=0; i<8; i++)
+ {
+ int v;
+ double sum= 0.0;
+
+ for(k=0; k<8; k++)
+ sum+= c[k*8+i]*tmp[8*k+j];
+
+ v= (int)floor(sum+0.5);
+ if(v<0) v=0;
+ else if(v>255) v=255;
+
+ dst[dstStride*i + j] = v;
+ }
+ }
+}
+
+static void drawDc(uint8_t *dst, int stride, int color, int w, int h)
+{
+ int y;
+ for(y=0; y<h; y++)
+ {
+ int x;
+ for(x=0; x<w; x++)
+ {
+ dst[x + y*stride]= color;
+ }
+ }
+}
+
+static void drawBasis(uint8_t *dst, int stride, int amp, int freq, int dc)
+{
+ int src[64];
+
+ memset(src, 0, 64*sizeof(int));
+ src[0]= dc;
+ if(amp) src[freq]= amp;
+ idct(dst, stride, src);
+}
+
+static void drawCbp(uint8_t *dst[3], int stride[3], int cbp, int amp, int dc)
+{
+ if(cbp&1) drawBasis(dst[0] , stride[0], amp, 1, dc);
+ if(cbp&2) drawBasis(dst[0]+8 , stride[0], amp, 1, dc);
+ if(cbp&4) drawBasis(dst[0]+ 8*stride[0], stride[0], amp, 1, dc);
+ if(cbp&8) drawBasis(dst[0]+8+8*stride[0], stride[0], amp, 1, dc);
+ if(cbp&16)drawBasis(dst[1] , stride[1], amp, 1, dc);
+ if(cbp&32)drawBasis(dst[2] , stride[2], amp, 1, dc);
+}
+
+static void dc1Test(uint8_t *dst, int stride, int w, int h, int off)
+{
+ const int step= MAX(256/(w*h/256), 1);
+ int y;
+ int color=off;
+ for(y=0; y<h; y+=16)
+ {
+ int x;
+ for(x=0; x<w; x+=16)
+ {
+ drawDc(dst + x + y*stride, stride, color, 8, 8);
+ color+=step;
+ }
+ }
+}
+
+static void freq1Test(uint8_t *dst, int stride, int off)
+{
+ int y;
+ int freq=0;
+ for(y=0; y<8*16; y+=16)
+ {
+ int x;
+ for(x=0; x<8*16; x+=16)
+ {
+ drawBasis(dst + x + y*stride, stride, 4*(96+off), freq, 128*8);
+ freq++;
+ }
+ }
+}
+
+static void amp1Test(uint8_t *dst, int stride, int off)
+{
+ int y;
+ int amp=off;
+ for(y=0; y<16*16; y+=16)
+ {
+ int x;
+ for(x=0; x<16*16; x+=16)
+ {
+ drawBasis(dst + x + y*stride, stride, 4*(amp), 1, 128*8);
+ amp++;
+ }
+ }
+}
+
+static void cbp1Test(uint8_t *dst[3], int stride[3], int off)
+{
+ int y;
+ int cbp=0;
+ for(y=0; y<16*8; y+=16)
+ {
+ int x;
+ for(x=0; x<16*8; x+=16)
+ {
+ uint8_t *dst1[3];
+ dst1[0]= dst[0] + x*2 + y*2*stride[0];
+ dst1[1]= dst[1] + x + y*stride[1];
+ dst1[2]= dst[2] + x + y*stride[2];
+
+ drawCbp(dst1, stride, cbp, (64+off)*4, 128*8);
+ cbp++;
+ }
+ }
+}
+
+static void mv1Test(uint8_t *dst, int stride, int off)
+{
+ int y;
+ for(y=0; y<16*16; y++)
+ {
+ int x;
+ if(y&16) continue;
+ for(x=0; x<16*16; x++)
+ {
+ dst[x + y*stride]= x + off*8/(y/32+1);
+ }
+ }
+}
+
+static void ring1Test(uint8_t *dst, int stride, int off)
+{
+ int y;
+ int color=0;
+ for(y=off; y<16*16; y+=16)
+ {
+ int x;
+ for(x=off; x<16*16; x+=16)
+ {
+ drawDc(dst + x + y*stride, stride, ((x+y)&16) ? color : -color, 16, 16);
+// dst[x + y*stride]= 255 + (off&1);
+ color++;
+ }
+ }
+}
+
+static void ring2Test(uint8_t *dst, int stride, int off)
+{
+ int y;
+ for(y=0; y<16*16; y++)
+ {
+ int x;
+ for(x=0; x<16*16; x++)
+ {
+ double d= sqrt((x-8*16)*(x-8*16) + (y-8*16)*(y-8*16));
+ double r= d/20 - (int)(d/20);
+ if(r<off/30.0)
+ {
+ dst[x + y*stride]= 255;
+ dst[x + y*stride+256]= 0;
+ }
+ else{
+ dst[x + y*stride]= x;
+ dst[x + y*stride+256]= x;
+ }
+ }
+ }
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ int frame= vf->priv->frame_num;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,IMGFMT_YV12,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ WIDTH, HEIGHT);
+
+ // clean
+ memset(dmpi->planes[0], 0, dmpi->stride[0]*dmpi->h);
+ memset(dmpi->planes[1], 128, dmpi->stride[1]*dmpi->h>>dmpi->chroma_y_shift);
+ memset(dmpi->planes[2], 128, dmpi->stride[2]*dmpi->h>>dmpi->chroma_y_shift);
+
+ if(frame%30)
+ {
+ switch(frame/30)
+ {
+ case 0: dc1Test(dmpi->planes[0], dmpi->stride[0], 256, 256, frame%30); break;
+ case 1: dc1Test(dmpi->planes[1], dmpi->stride[1], 256, 256, frame%30); break;
+ case 2: freq1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
+ case 3: freq1Test(dmpi->planes[1], dmpi->stride[1], frame%30); break;
+ case 4: amp1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
+ case 5: amp1Test(dmpi->planes[1], dmpi->stride[1], frame%30); break;
+ case 6: cbp1Test(dmpi->planes , dmpi->stride , frame%30); break;
+ case 7: mv1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
+ case 8: ring1Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
+ case 9: ring2Test(dmpi->planes[0], dmpi->stride[0], frame%30); break;
+ }
+ }
+
+ frame++;
+ vf->priv->frame_num= frame;
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ return vf_next_query_format(vf,IMGFMT_YV12) & (~VFCAP_CSP_SUPPORTED_BY_HW);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ vf->priv->frame_num= args ? atoi(args) : 0;
+ initIdct();
+ return 1;
+}
+
+const vf_info_t vf_info_test = {
+ "test pattern generator",
+ "test",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_tile.c b/libavfilter/libmpcodecs/vf_tile.c
new file mode 100644
index 0000000000..9ec037ef4c
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_tile.c
@@ -0,0 +1,330 @@
+/*
+ * filter to tile a serie of image in a single, bigger, image
+ *
+ * The parameters are:
+ *
+ * xtile: number of tile on the x axis (5)
+ * ytile: number of tile on the y axis (5)
+ * xytile: when write the image, it can be different then xtile * ytile
+ * (for example you can write 8 * 7 tile, writing the file every
+ * 50 frame, to have one image every 2 seconds @ 25 fps ).
+ * start: pixel at the start (x/y), default 2
+ * delta: pixel between 2 tile, (x/y), default 4
+ *
+ * For example a valid command line is:
+ * ... -vf tile=10:5:-1:4:8 ...
+ * that make images of 10 * 5 tiles, with 4 pixel at the beginning and
+ * 8 pixel between tiles.
+ *
+ * The default command is:
+ * ... -vf tile=5:5:25:2:4
+ *
+ * If you omit a parameter or put a value less then 0, the default is used.
+ * ... -vf tile=10:5::-1:10
+ *
+ * You can also stop when you're ok
+ * ... -vf tile=10:5
+ * (and this is probably the option you will use more often ...)
+ *
+ * Probably is good to put the scale filter before the tile :-)
+ *
+ * copyright (c) 2003 Daniele Forghieri ( guru@digitalfantasy.it )
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+// strtoi memcpy_pic
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+#include "cpudetect.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+/* private data */
+struct vf_priv_s {
+ /* configuration data */
+ /* Number on hor/ver tiles */
+ int xtile;
+ int ytile;
+ /* When write the whole frame (default = xtile * ytile) */
+ int xytile;
+ /* pixel at start / end (default = 4) */
+ int start;
+ /* pixel between image (default = 2) */
+ int delta;
+// /* Background color, in destination format */
+// int bkgSet;
+
+ /* Work data */
+ int frame_cur;
+};
+
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ struct vf_priv_s *priv;
+ int xw;
+ int yh;
+
+ /* Calculate new destination size */
+ priv = vf->priv;
+ xw = priv->start * 2 +
+ priv->xtile * width +
+ (priv->xtile - 1) * priv->delta;
+ yh = priv->start * 2 +
+ priv->ytile * height +
+ (priv->ytile - 1) * priv->delta;
+
+ mp_msg(MSGT_VFILTER,MSGL_V,"vf_tile:config size set to %d * %d\n", xw, yh);
+
+ return vf_next_config(vf, xw, yh, xw, yh, flags, outfmt);
+}
+
+/* Filter handler */
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ mp_image_t *dmpi;
+ struct vf_priv_s *priv;
+ int t;
+ int xw;
+ int yh;
+ int xi;
+ int yi;
+ int by;
+ int dw;
+
+ /* Calculate new size */
+ priv = vf->priv;
+ xw = priv->start * 2 +
+ priv->xtile * mpi->w +
+ (priv->xtile - 1) * priv->delta;
+ yh = priv->start * 2 +
+ priv->ytile * mpi->h+
+ (priv->ytile - 1) * priv->delta;
+
+ /* Get the big image! */
+ dmpi=vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE,
+ xw, yh);
+
+ /* bytes x pixel & bytes x line */
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ by = 1;
+ dw = mpi->w;
+ }
+ else {
+ by = (mpi->bpp + 7) / 8;
+ dw = mpi->w * by;
+ }
+ /* Index position */
+ t = priv->frame_cur % priv->xytile;
+// if ((t == 0) && (bkg != 0)) {
+// /* First frame, delete the background */
+//
+// }
+
+ /* Position of image */
+ xi = priv->start + (mpi->w + priv->delta) * (t % priv->xtile);
+ yi = priv->start + (mpi->h + priv->delta) * (t / priv->xtile);
+
+ /* Copy first (or only) plane */
+ memcpy_pic( dmpi->planes[0] + xi * by + yi * dmpi->stride[0],
+ mpi->planes[0],
+ dw,
+ mpi->h,
+ dmpi->stride[0],
+ mpi->stride[0]);
+
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ /* Copy the other 2 planes */
+ memcpy_pic( dmpi->planes[1] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[1],
+ mpi->planes[1],
+ mpi->chroma_width,
+ mpi->chroma_height,
+ dmpi->stride[1],
+ mpi->stride[1]);
+ memcpy_pic( dmpi->planes[2] + (xi >> mpi->chroma_x_shift) + (yi >> mpi->chroma_y_shift) * dmpi->stride[2],
+ mpi->planes[2],
+ mpi->chroma_width,
+ mpi->chroma_height,
+ dmpi->stride[2],
+ mpi->stride[2]);
+ }
+
+ /* Increment current frame */
+ ++priv->frame_cur;
+
+ if (t == priv->xytile - 1) {
+ /* Display the composition */
+ dmpi->width = xw;
+ dmpi->height = yh;
+ return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ }
+ else {
+ /* Skip the frame */
+ return 0;
+ }
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ /* free local data */
+ free(vf->priv);
+}
+
+/* rgb/bgr 12...32 supported & some Yxxx */
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ switch (fmt) {
+ /* rgb 12...32 bit */
+ case IMGFMT_RGB12:
+ case IMGFMT_RGB15:
+ case IMGFMT_RGB16:
+ case IMGFMT_RGB24:
+ case IMGFMT_RGB32:
+ /* bgr 12...32 bit */
+ case IMGFMT_BGR12:
+ case IMGFMT_BGR15:
+ case IMGFMT_BGR16:
+ case IMGFMT_BGR24:
+ case IMGFMT_BGR32:
+ /* Various Yxxx Formats */
+ case IMGFMT_444P:
+ case IMGFMT_422P:
+ case IMGFMT_411P:
+ case IMGFMT_YUY2:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_IYUV:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+/* Get an integer from the string pointed by s, adjusting s.
+ * If the value is less then 0 def_val is used.
+ * Return 0 for ok
+ *
+ * Look below ( in vf_open(...) ) for a use ...
+ */
+static int parse_int(char **s, int *rt, int def_val)
+{
+
+ int t = 0;
+
+ if (**s) {
+ /* Get value (dec, hex or octal) */
+ t = strtol( *s, s, 0 );
+
+ /* Use default */
+ if (t < 0) {
+ t = def_val;
+ }
+
+ if (**s == ':') {
+ /* Point to next character (problably a digit) */
+ ++(*s);
+ }
+ else if (**s != '\0') {
+ /* Error, we got some wrong char */
+ return 1;
+ }
+ }
+ else {
+ t = def_val;
+ }
+
+ *rt = t;
+ return 0;
+
+}
+
+/* Main entry funct for the filter */
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ int er;
+
+ vf->put_image = put_image;
+ vf->query_format = query_format;
+ vf->config = config;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ /* Private data */
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ if (p == NULL) {
+ return 0;
+ }
+
+ if (args == NULL) {
+ /* Use the default */
+ args = "";
+ }
+ /* Parse all the arguments */
+ er = parse_int( &args, &p->xtile, 5 );
+ er |= parse_int( &args, &p->ytile, 5 );
+ er |= parse_int( &args, &p->xytile, 0 );
+ er |= parse_int( &args, &p->start, 2 );
+ er |= parse_int( &args, &p->delta, 4 );
+// er |= parse_int( &args, &p->bkgSet, 0 );
+
+ if (er) {
+ mp_msg(MSGT_VFILTER, MSGL_ERR, MSGTR_MPCODECS_ErrorParsingArgument);
+ return 0;
+ }
+ /* Load some default */
+ if ((p->xytile <= 0) || (p->xytile > p->xtile * p->ytile)) {
+ p->xytile = p->xtile * p->ytile;
+ }
+
+ /* Say what happen: use mp_msg(...)? */
+ if ( mp_msg_test(MSGT_VFILTER,MSGL_V) ) {
+ printf("vf_tile: tiling %d * %d, output every %d frames\n",
+ p->xtile,
+ p->ytile,
+ p->xytile);
+ printf("vf_tile: start pixel %d, delta pixel %d\n",
+ p->start,
+ p->delta);
+// printf("vf_tile: background 0x%x\n",
+// p->bkgSet);
+ }
+ return 1;
+}
+
+const vf_info_t vf_info_tile = {
+ "Make a single image tiling x/y images",
+ "tile",
+ "Daniele Forghieri",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_tinterlace.c b/libavfilter/libmpcodecs/vf_tinterlace.c
new file mode 100644
index 0000000000..6dbcbc9481
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_tinterlace.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2003 Michael Zucchi <notzed@ximian.com>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+struct vf_priv_s {
+ int mode;
+ int frame;
+ mp_image_t *dmpi;
+};
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+{
+ int ret = 0;
+ mp_image_t *dmpi;
+
+ switch (vf->priv->mode) {
+ case 0:
+ dmpi = vf->priv->dmpi;
+ if (dmpi == NULL) {
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE,
+ mpi->width, mpi->height*2);
+
+ vf->priv->dmpi = dmpi;
+
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0]*2, mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1]*2, mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2]*2, mpi->stride[2]);
+ }
+ } else {
+ vf->priv->dmpi = NULL;
+
+ memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0]*2, mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1]+dmpi->stride[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1]*2, mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2]+dmpi->stride[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2]*2, mpi->stride[2]);
+ }
+ ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ }
+ break;
+ case 1:
+ if (vf->priv->frame & 1)
+ ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
+ break;
+ case 2:
+ if ((vf->priv->frame & 1) == 0)
+ ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
+ break;
+ case 3:
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->width, mpi->height*2);
+ /* fixme, just clear alternate lines */
+ vf_mpi_clear(dmpi, 0, 0, dmpi->w, dmpi->h);
+ if ((vf->priv->frame & 1) == 0) {
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0]*2, mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1]*2, mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2]*2, mpi->stride[2]);
+ }
+ } else {
+ memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0], mpi->w, mpi->h,
+ dmpi->stride[0]*2, mpi->stride[0]);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ memcpy_pic(dmpi->planes[1]+dmpi->stride[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1]*2, mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2]+dmpi->stride[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2]*2, mpi->stride[2]);
+ }
+ }
+ ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ break;
+ case 4:
+ // Interleave even lines (only) from Frame 'i' with odd
+ // lines (only) from Frame 'i+1', halving the Frame
+ // rate and preserving image height.
+
+ dmpi = vf->priv->dmpi;
+
+ // @@ Need help: Should I set dmpi->fields to indicate
+ // that the (new) frame will be interlaced!? E.g. ...
+ // dmpi->fields |= MP_IMGFIELD_INTERLACED;
+ // dmpi->fields |= MP_IMGFIELD_TOP_FIRST;
+ // etc.
+
+ if (dmpi == NULL) {
+ dmpi = vf_get_image(vf->next, mpi->imgfmt,
+ MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
+ MP_IMGFLAG_PRESERVE,
+ mpi->width, mpi->height);
+
+ vf->priv->dmpi = dmpi;
+
+ my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ } else {
+ vf->priv->dmpi = NULL;
+
+ my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
+ mpi->planes[0]+mpi->stride[0],
+ mpi->w, mpi->h/2,
+ dmpi->stride[0]*2, mpi->stride[0]*2);
+ if (mpi->flags & MP_IMGFLAG_PLANAR) {
+ my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
+ mpi->planes[1]+mpi->stride[1],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[1]*2, mpi->stride[1]*2);
+ my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
+ mpi->planes[2]+mpi->stride[2],
+ mpi->chroma_width, mpi->chroma_height/2,
+ dmpi->stride[2]*2, mpi->stride[2]*2);
+ }
+ ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+ }
+ break;
+ }
+
+ vf->priv->frame++;
+
+ return ret;
+}
+
+static int query_format(struct vf_instance *vf, unsigned int fmt)
+{
+ /* FIXME - figure out which other formats work */
+ switch (fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return vf_next_query_format(vf, fmt);
+ }
+ return 0;
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt)
+{
+ switch (vf->priv->mode) {
+ case 0:
+ case 3:
+ return vf_next_config(vf,width,height*2,d_width,d_height*2,flags,outfmt);
+ case 1: /* odd frames */
+ case 2: /* even frames */
+ case 4: /* alternate frame (height-preserving) interlacing */
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+ }
+ return 0;
+}
+
+static void uninit(struct vf_instance *vf)
+{
+ free(vf->priv);
+}
+
+static int vf_open(vf_instance_t *vf, char *args)
+{
+ struct vf_priv_s *p;
+ vf->config = config;
+ vf->put_image = put_image;
+ vf->query_format = query_format;
+ vf->uninit = uninit;
+ vf->default_reqs = VFCAP_ACCEPT_STRIDE;
+ vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
+ vf->priv->mode = 0;
+ if (args)
+ sscanf(args, "%d", &vf->priv->mode);
+ vf->priv->frame = 0;
+ return 1;
+}
+
+const vf_info_t vf_info_tinterlace = {
+ "temporal field interlacing",
+ "tinterlace",
+ "Michael Zucchi",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_unsharp.c b/libavfilter/libmpcodecs/vf_unsharp.c
new file mode 100644
index 0000000000..cd464321f4
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_unsharp.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2002 Remi Guyomarch <rguyom@pobox.com>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "libvo/fastmemcpy.h"
+#include "libavutil/common.h"
+
+//===========================================================================//
+
+#define MIN_MATRIX_SIZE 3
+#define MAX_MATRIX_SIZE 63
+
+typedef struct FilterParam {
+ int msizeX, msizeY;
+ double amount;
+ uint32_t *SC[MAX_MATRIX_SIZE-1];
+} FilterParam;
+
+struct vf_priv_s {
+ FilterParam lumaParam;
+ FilterParam chromaParam;
+ unsigned int outfmt;
+};
+
+
+//===========================================================================//
+
+/* This code is based on :
+
+An Efficient algorithm for Gaussian blur using finite-state machines
+Frederick M. Waltz and John W. V. Miller
+
+SPIE Conf. on Machine Vision Systems for Inspection and Metrology VII
+Originally published Boston, Nov 98
+
+*/
+
+static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp ) {
+
+ uint32_t **SC = fp->SC;
+ uint32_t SR[MAX_MATRIX_SIZE-1], Tmp1, Tmp2;
+ uint8_t* src2 = src; // avoid gcc warning
+
+ int32_t res;
+ int x, y, z;
+ int amount = fp->amount * 65536.0;
+ int stepsX = fp->msizeX/2;
+ int stepsY = fp->msizeY/2;
+ int scalebits = (stepsX+stepsY)*2;
+ int32_t halfscale = 1 << ((stepsX+stepsY)*2-1);
+
+ if( !fp->amount ) {
+ if( src == dst )
+ return;
+ if( dstStride == srcStride )
+ fast_memcpy( dst, src, srcStride*height );
+ else
+ for( y=0; y<height; y++, dst+=dstStride, src+=srcStride )
+ fast_memcpy( dst, src, width );
+ return;
+ }
+
+ for( y=0; y<2*stepsY; y++ )
+ memset( SC[y], 0, sizeof(SC[y][0]) * (width+2*stepsX) );
+
+ for( y=-stepsY; y<height+stepsY; y++ ) {
+ if( y < height ) src2 = src;
+ memset( SR, 0, sizeof(SR[0]) * (2*stepsX-1) );
+ for( x=-stepsX; x<width+stepsX; x++ ) {
+ Tmp1 = x<=0 ? src2[0] : x>=width ? src2[width-1] : src2[x];
+ for( z=0; z<stepsX*2; z+=2 ) {
+ Tmp2 = SR[z+0] + Tmp1; SR[z+0] = Tmp1;
+ Tmp1 = SR[z+1] + Tmp2; SR[z+1] = Tmp2;
+ }
+ for( z=0; z<stepsY*2; z+=2 ) {
+ Tmp2 = SC[z+0][x+stepsX] + Tmp1; SC[z+0][x+stepsX] = Tmp1;
+ Tmp1 = SC[z+1][x+stepsX] + Tmp2; SC[z+1][x+stepsX] = Tmp2;
+ }
+ if( x>=stepsX && y>=stepsY ) {
+ uint8_t* srx = src - stepsY*srcStride + x - stepsX;
+ uint8_t* dsx = dst - stepsY*dstStride + x - stepsX;
+
+ res = (int32_t)*srx + ( ( ( (int32_t)*srx - (int32_t)((Tmp1+halfscale) >> scalebits) ) * amount ) >> 16 );
+ *dsx = res>255 ? 255 : res<0 ? 0 : (uint8_t)res;
+ }
+ }
+ if( y >= 0 ) {
+ dst += dstStride;
+ src += srcStride;
+ }
+ }
+}
+
+//===========================================================================//
+
+static int config( struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt ) {
+
+ int z, stepsX, stepsY;
+ FilterParam *fp;
+ char *effect;
+
+ // allocate buffers
+
+ fp = &vf->priv->lumaParam;
+ effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
+ mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s luma) \n", fp->msizeX, fp->msizeY, fp->amount, effect );
+ memset( fp->SC, 0, sizeof( fp->SC ) );
+ stepsX = fp->msizeX/2;
+ stepsY = fp->msizeY/2;
+ for( z=0; z<2*stepsY; z++ )
+ fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
+
+ fp = &vf->priv->chromaParam;
+ effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
+ mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s chroma)\n", fp->msizeX, fp->msizeY, fp->amount, effect );
+ memset( fp->SC, 0, sizeof( fp->SC ) );
+ stepsX = fp->msizeX/2;
+ stepsY = fp->msizeY/2;
+ for( z=0; z<2*stepsY; z++ )
+ fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
+
+ return vf_next_config( vf, width, height, d_width, d_height, flags, outfmt );
+}
+
+//===========================================================================//
+
+static void get_image( struct vf_instance *vf, mp_image_t *mpi ) {
+ if( mpi->flags & MP_IMGFLAG_PRESERVE )
+ return; // don't change
+ if( mpi->imgfmt!=vf->priv->outfmt )
+ return; // colorspace differ
+
+ vf->dmpi = vf_get_image( vf->next, mpi->imgfmt, mpi->type, mpi->flags, mpi->w, mpi->h );
+ mpi->planes[0] = vf->dmpi->planes[0];
+ mpi->stride[0] = vf->dmpi->stride[0];
+ mpi->width = vf->dmpi->width;
+ if( mpi->flags & MP_IMGFLAG_PLANAR ) {
+ mpi->planes[1] = vf->dmpi->planes[1];
+ mpi->planes[2] = vf->dmpi->planes[2];
+ mpi->stride[1] = vf->dmpi->stride[1];
+ mpi->stride[2] = vf->dmpi->stride[2];
+ }
+ mpi->flags |= MP_IMGFLAG_DIRECT;
+}
+
+static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) {
+ mp_image_t *dmpi;
+
+ if( !(mpi->flags & MP_IMGFLAG_DIRECT) )
+ // no DR, so get a new image! hope we'll get DR buffer:
+ vf->dmpi = vf_get_image( vf->next,vf->priv->outfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w, mpi->h);
+ dmpi= vf->dmpi;
+
+ unsharp( dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam );
+ unsharp( dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
+ unsharp( dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
+
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX)
+ __asm__ volatile ("emms\n\t");
+#endif
+#if HAVE_MMX2
+ if(gCpuCaps.hasMMX2)
+ __asm__ volatile ("sfence\n\t");
+#endif
+
+ return vf_next_put_image( vf, dmpi, pts);
+}
+
+static void uninit( struct vf_instance *vf ) {
+ unsigned int z;
+ FilterParam *fp;
+
+ if( !vf->priv ) return;
+
+ fp = &vf->priv->lumaParam;
+ for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
+ av_free( fp->SC[z] );
+ fp->SC[z] = NULL;
+ }
+ fp = &vf->priv->chromaParam;
+ for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
+ av_free( fp->SC[z] );
+ fp->SC[z] = NULL;
+ }
+
+ free( vf->priv );
+ vf->priv = NULL;
+}
+
+//===========================================================================//
+
+static int query_format( struct vf_instance *vf, unsigned int fmt ) {
+ switch(fmt) {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ return vf_next_query_format( vf, vf->priv->outfmt );
+ }
+ return 0;
+}
+
+//===========================================================================//
+
+static void parse( FilterParam *fp, char* args ) {
+
+ // l7x5:0.8:c3x3:-0.2
+
+ char *z;
+ char *pos = args;
+ char *max = args + strlen(args);
+
+ // parse matrix sizes
+ fp->msizeX = ( pos && pos+1<max ) ? atoi( pos+1 ) : 0;
+ z = strchr( pos+1, 'x' );
+ fp->msizeY = ( z && z+1<max ) ? atoi( pos=z+1 ) : fp->msizeX;
+
+ // min/max & odd
+ fp->msizeX = 1 | av_clip(fp->msizeX, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
+ fp->msizeY = 1 | av_clip(fp->msizeY, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
+
+ // parse amount
+ pos = strchr( pos+1, ':' );
+ fp->amount = ( pos && pos+1<max ) ? atof( pos+1 ) : 0;
+}
+
+//===========================================================================//
+
+static const unsigned int fmt_list[] = {
+ IMGFMT_YV12,
+ IMGFMT_I420,
+ IMGFMT_IYUV,
+ 0
+};
+
+static int vf_open( vf_instance_t *vf, char *args ) {
+ vf->config = config;
+ vf->put_image = put_image;
+ vf->get_image = get_image;
+ vf->query_format = query_format;
+ vf->uninit = uninit;
+ vf->priv = malloc( sizeof(struct vf_priv_s) );
+ memset( vf->priv, 0, sizeof(struct vf_priv_s) );
+
+ if( args ) {
+ char *args2 = strchr( args, 'l' );
+ if( args2 )
+ parse( &vf->priv->lumaParam, args2 );
+ else {
+ vf->priv->lumaParam.amount =
+ vf->priv->lumaParam.msizeX =
+ vf->priv->lumaParam.msizeY = 0;
+ }
+
+ args2 = strchr( args, 'c' );
+ if( args2 )
+ parse( &vf->priv->chromaParam, args2 );
+ else {
+ vf->priv->chromaParam.amount =
+ vf->priv->chromaParam.msizeX =
+ vf->priv->chromaParam.msizeY = 0;
+ }
+
+ if( !vf->priv->lumaParam.msizeX && !vf->priv->chromaParam.msizeX )
+ return 0; // nothing to do
+ }
+
+ // check csp:
+ vf->priv->outfmt = vf_match_csp( &vf->next, fmt_list, IMGFMT_YV12 );
+ if( !vf->priv->outfmt ) {
+ uninit( vf );
+ return 0; // no csp match :(
+ }
+
+ return 1;
+}
+
+const vf_info_t vf_info_unsharp = {
+ "unsharp mask & gaussian blur",
+ "unsharp",
+ "Remi Guyomarch",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_uspp.c b/libavfilter/libmpcodecs/vf_uspp.c
new file mode 100644
index 0000000000..7f5a86522a
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_uspp.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+#include <assert.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "cpudetect.h"
+
+#include "libavcodec/avcodec.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "vd_ffmpeg.h"
+#include "libvo/fastmemcpy.h"
+
+#define XMIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define BLOCK 16
+
+//===========================================================================//
+static const uint8_t __attribute__((aligned(8))) dither[8][8]={
+{ 0*4, 48*4, 12*4, 60*4, 3*4, 51*4, 15*4, 63*4, },
+{ 32*4, 16*4, 44*4, 28*4, 35*4, 19*4, 47*4, 31*4, },
+{ 8*4, 56*4, 4*4, 52*4, 11*4, 59*4, 7*4, 55*4, },
+{ 40*4, 24*4, 36*4, 20*4, 43*4, 27*4, 39*4, 23*4, },
+{ 2*4, 50*4, 14*4, 62*4, 1*4, 49*4, 13*4, 61*4, },
+{ 34*4, 18*4, 46*4, 30*4, 33*4, 17*4, 45*4, 29*4, },
+{ 10*4, 58*4, 6*4, 54*4, 9*4, 57*4, 5*4, 53*4, },
+{ 42*4, 26*4, 38*4, 22*4, 41*4, 25*4, 37*4, 21*4, },
+};
+
+static const uint8_t offset[511][2]= {
+{ 0, 0},
+{ 0, 0}, { 8, 8},
+{ 0, 0}, { 4, 4}, {12, 8}, { 8,12},
+{ 0, 0}, {10, 2}, { 4, 4}, {14, 6}, { 8, 8}, { 2,10}, {12,12}, { 6,14},
+
+{ 0, 0}, {10, 2}, { 4, 4}, {14, 6}, { 8, 8}, { 2,10}, {12,12}, { 6,14},
+{ 5, 1}, {15, 3}, { 9, 5}, { 3, 7}, {13, 9}, { 7,11}, { 1,13}, {11,15},
+
+{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9},
+{ 2, 2}, {10, 2}, { 2,10}, {10,10}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
+{ 4, 4}, {12, 4}, { 4,12}, {12,12}, { 1, 5}, { 9, 5}, { 1,13}, { 9,13},
+{ 6, 6}, {14, 6}, { 6,14}, {14,14}, { 3, 7}, {11, 7}, { 3,15}, {11,15},
+
+{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8},
+{ 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9},
+{ 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 2}, {15, 2}, { 7,10}, {15,10},
+{ 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 3}, {14, 3}, { 6,11}, {14,11},
+{ 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 4}, {12, 4}, { 4,12}, {12,12},
+{ 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 5}, {13, 5}, { 5,13}, {13,13},
+{ 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 6}, {15, 6}, { 7,14}, {15,14},
+{ 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 7}, {14, 7}, { 6,15}, {14,15},
+
+{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 0, 2}, { 8, 2}, { 0,10}, { 8,10},
+{ 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 0, 6}, { 8, 6}, { 0,14}, { 8,14},
+{ 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 1, 3}, { 9, 3}, { 1,11}, { 9,11},
+{ 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 1, 7}, { 9, 7}, { 1,15}, { 9,15},
+{ 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 2, 2}, {10, 2}, { 2,10}, {10,10},
+{ 2, 4}, {10, 4}, { 2,12}, {10,12}, { 2, 6}, {10, 6}, { 2,14}, {10,14},
+{ 3, 1}, {11, 1}, { 3, 9}, {11, 9}, { 3, 3}, {11, 3}, { 3,11}, {11,11},
+{ 3, 5}, {11, 5}, { 3,13}, {11,13}, { 3, 7}, {11, 7}, { 3,15}, {11,15},
+{ 4, 0}, {12, 0}, { 4, 8}, {12, 8}, { 4, 2}, {12, 2}, { 4,10}, {12,10},
+{ 4, 4}, {12, 4}, { 4,12}, {12,12}, { 4, 6}, {12, 6}, { 4,14}, {12,14},
+{ 5, 1}, {13, 1}, { 5, 9}, {13, 9}, { 5, 3}, {13, 3}, { 5,11}, {13,11},
+{ 5, 5}, {13, 5}, { 5,13}, {13,13}, { 5, 7}, {13, 7}, { 5,15}, {13,15},
+{ 6, 0}, {14, 0}, { 6, 8}, {14, 8}, { 6, 2}, {14, 2}, { 6,10}, {14,10},
+{ 6, 4}, {14, 4}, { 6,12}, {14,12}, { 6, 6}, {14, 6}, { 6,14}, {14,14},
+{ 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
+{ 7, 5}, {15, 5}, { 7,13}, {15,13}, { 7, 7}, {15, 7}, { 7,15}, {15,15},
+
+{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 4}, {12, 4}, { 4,12}, {12,12}, { 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8}, { 2, 2}, {10, 2}, { 2,10}, {10,10}, { 6, 6}, {14, 6}, { 6,14}, {14,14}, { 2, 6}, {10, 6}, { 2,14}, {10,14}, { 6, 2}, {14, 2}, { 6,10}, {14,10}, { 0, 2}, { 8, 2}, { 0,10}, { 8,10}, { 4, 6}, {12, 6}, { 4,14}, {12,14}, { 0, 6}, { 8, 6}, { 0,14}, { 8,14}, { 4, 2}, {12, 2}, { 4,10}, {12,10}, { 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 6, 4}, {14, 4}, { 6,12}, {14,12}, { 2, 4}, {10, 4}, { 2,12}, {10,12}, { 6, 0}, {14, 0}, { 6, 8}, {14, 8}, { 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 5}, {13, 5}, { 5,13}, {13,13}, { 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9}, { 3, 3}, {11, 3}, { 3,11}, {11,11}, { 7, 7}, {15, 7}, { 7,15}, {15,15}, { 3, 7}, {11, 7}, { 3,15}, {11,15}, { 7, 3}, {15, 3}, { 7,11}, {15,11}, { 1, 3}, { 9, 3}, { 1,11}, { 9,11}, { 5, 7}, {13, 7}, { 5,15}, {13,15}, { 1, 7}, { 9, 7}, { 1,15}, { 9,15}, { 5, 3}, {13, 3}, { 5,11}, {13,11}, { 3, 1}, {11, 1}, { 3, 9}, {11, 9}, { 7, 5}, {15, 5}, { 7,13}, {15,13}, { 3, 5}, {11, 5}, { 3,13}, {11,13}, { 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 0, 1}, { 8, 1}, { 0, 9}, { 8, 9}, { 4, 5}, {12, 5}, { 4,13}, {12,13}, { 0, 5}, { 8, 5}, { 0,13}, { 8,13}, { 4, 1}, {12, 1}, { 4, 9}, {12, 9}, { 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 7}, {14, 7}, { 6,15}, {14,15}, { 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 3}, {14, 3}, { 6,11}, {14,11}, { 0, 3}, { 8, 3}, { 0,11}, { 8,11}, { 4, 7}, {12, 7}, { 4,15}, {12,15}, { 0, 7}, { 8, 7}, { 0,15}, { 8,15}, { 4, 3}, {12, 3}, { 4,11}, {12,11}, { 2, 1}, {10, 1}, { 2, 9}, {10, 9}, { 6, 5}, {14, 5}, { 6,13}, {14,13}, { 2, 5}, {10, 5}, { 2,13}, {10,13}, { 6, 1}, {14, 1}, { 6, 9}, {14, 9}, { 1, 0}, { 9, 0}, { 1, 8}, { 9, 8}, { 5, 4}, {13, 4}, { 5,12}, {13,12}, { 1, 4}, { 9, 4}, { 1,12}, { 9,12}, { 5, 0}, {13, 0}, { 5, 8}, {13, 8}, { 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 6}, {15, 6}, { 7,14}, {15,14}, { 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 2}, {15, 2}, { 7,10}, {15,10}, { 1, 2}, { 9, 2}, { 1,10}, { 9,10}, { 5, 6}, {13, 6}, { 5,14}, {13,14}, { 1, 6}, { 9, 6}, { 1,14}, { 9,14}, { 5, 2}, {13, 2}, { 5,10}, {13,10}, { 3, 0}, {11, 0}, { 3, 8}, {11, 8}, { 7, 4}, {15, 4}, { 7,12}, {15,12}, { 3, 4}, {11, 4}, { 3,12}, {11,12}, { 7, 0}, {15, 0}, { 7, 8}, {15, 8},
+};
+
+struct vf_priv_s {
+ int log2_count;
+ int qp;
+ int mode;
+ int mpeg2;
+ int temp_stride[3];
+ uint8_t *src[3];
+ int16_t *temp[3];
+ int outbuf_size;
+ uint8_t *outbuf;
+ AVCodecContext *avctx_enc[BLOCK*BLOCK];
+ AVFrame *frame;
+ AVFrame *frame_dec;
+};
+
+static void store_slice_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale){
+ int y, x;
+
+#define STORE(pos) \
+ temp= ((src[x + y*src_stride + pos]<<log2_scale) + d[pos])>>8;\
+ if(temp & 0x100) temp= ~(temp>>31);\
+ dst[x + y*dst_stride + pos]= temp;
+
+ for(y=0; y<height; y++){
+ const uint8_t *d= dither[y&7];
+ for(x=0; x<width; x+=8){
+ int temp;
+ STORE(0);
+ STORE(1);
+ STORE(2);
+ STORE(3);
+ STORE(4);
+ STORE(5);
+ STORE(6);
+ STORE(7);
+ }
+ }
+}
+
+static void filter(struct vf_priv_s *p, uint8_t *dst[3], uint8_t *src[3], int dst_stride[3], int src_stride[3], int width, int height, uint8_t *qp_store, int qp_stride){
+ int x, y, i, j;
+ const int count= 1<<p->log2_count;
+
+ for(i=0; i<3; i++){
+ int is_chroma= !!i;
+ int w= width >>is_chroma;
+ int h= height>>is_chroma;
+ int stride= p->temp_stride[i];
+ int block= BLOCK>>is_chroma;
+
+ if (!src[i] || !dst[i])
+ continue; // HACK avoid crash for Y8 colourspace
+ for(y=0; y<h; y++){
+ int index= block + block*stride + y*stride;
+ fast_memcpy(p->src[i] + index, src[i] + y*src_stride[i], w);
+ for(x=0; x<block; x++){
+ p->src[i][index - x - 1]= p->src[i][index + x ];
+ p->src[i][index + w + x ]= p->src[i][index + w - x - 1];
+ }
+ }
+ for(y=0; y<block; y++){
+ fast_memcpy(p->src[i] + ( block-1-y)*stride, p->src[i] + ( y+block )*stride, stride);
+ fast_memcpy(p->src[i] + (h+block +y)*stride, p->src[i] + (h-y+block-1)*stride, stride);
+ }
+
+ p->frame->linesize[i]= stride;
+ memset(p->temp[i], 0, (h+2*block)*stride*sizeof(int16_t));
+ }
+
+ if(p->qp)
+ p->frame->quality= p->qp * FF_QP2LAMBDA;
+ else
+ p->frame->quality= norm_qscale(qp_store[0], p->mpeg2) * FF_QP2LAMBDA;
+// init per MB qscale stuff FIXME
+
+ for(i=0; i<count; i++){
+ const int x1= offset[i+count-1][0];
+ const int y1= offset[i+count-1][1];
+ int offset, out_size;
+ p->frame->data[0]= p->src[0] + x1 + y1 * p->frame->linesize[0];
+ p->frame->data[1]= p->src[1] + x1/2 + y1/2 * p->frame->linesize[1];
+ p->frame->data[2]= p->src[2] + x1/2 + y1/2 * p->frame->linesize[2];
+
+ out_size = avcodec_encode_video(p->avctx_enc[i], p->outbuf, p->outbuf_size, p->frame);
+ p->frame_dec = p->avctx_enc[i]->coded_frame;
+
+ offset= (BLOCK-x1) + (BLOCK-y1)*p->frame_dec->linesize[0];
+ //FIXME optimize
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ p->temp[0][ x + y*p->temp_stride[0] ] += p->frame_dec->data[0][ x + y*p->frame_dec->linesize[0] + offset ];
+ }
+ }
+ offset= (BLOCK/2-x1/2) + (BLOCK/2-y1/2)*p->frame_dec->linesize[1];
+ for(y=0; y<height/2; y++){
+ for(x=0; x<width/2; x++){
+ p->temp[1][ x + y*p->temp_stride[1] ] += p->frame_dec->data[1][ x + y*p->frame_dec->linesize[1] + offset ];
+ p->temp[2][ x + y*p->temp_stride[2] ] += p->frame_dec->data[2][ x + y*p->frame_dec->linesize[2] + offset ];
+ }
+ }
+ }
+
+ for(j=0; j<3; j++){
+ int is_chroma= !!j;
+ store_slice_c(dst[j], p->temp[j], dst_stride[j], p->temp_stride[j], width>>is_chroma, height>>is_chroma, 8-p->log2_count);
+ }
+}
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ int i;
+ AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
+
+ for(i=0; i<3; i++){
+ int is_chroma= !!i;
+ int w= ((width + 4*BLOCK-1) & (~(2*BLOCK-1)))>>is_chroma;
+ int h= ((height + 4*BLOCK-1) & (~(2*BLOCK-1)))>>is_chroma;
+
+ vf->priv->temp_stride[i]= w;
+ vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
+ vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
+ }
+ for(i=0; i< (1<<vf->priv->log2_count); i++){
+ AVCodecContext *avctx_enc;
+
+ avctx_enc=
+ vf->priv->avctx_enc[i]= avcodec_alloc_context();
+ avctx_enc->width = width + BLOCK;
+ avctx_enc->height = height + BLOCK;
+ avctx_enc->time_base= (AVRational){1,25}; // meaningless
+ avctx_enc->gop_size = 300;
+ avctx_enc->max_b_frames= 0;
+ avctx_enc->pix_fmt = PIX_FMT_YUV420P;
+ avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
+ avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
+ avctx_enc->global_quality= 123;
+ avcodec_open(avctx_enc, enc);
+ assert(avctx_enc->codec);
+ }
+ vf->priv->frame= avcodec_alloc_frame();
+ vf->priv->frame_dec= avcodec_alloc_frame();
+
+ vf->priv->outbuf_size= (width + BLOCK)*(height + BLOCK)*10;
+ vf->priv->outbuf= malloc(vf->priv->outbuf_size);
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
+}
+
+static void get_image(struct vf_instance *vf, mp_image_t *mpi){
+ if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
+ // ok, we can do pp in-place (or pp disabled):
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
+ mpi->planes[0]=vf->dmpi->planes[0];
+ mpi->stride[0]=vf->dmpi->stride[0];
+ mpi->width=vf->dmpi->width;
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[1]=vf->dmpi->planes[1];
+ mpi->planes[2]=vf->dmpi->planes[2];
+ mpi->stride[1]=vf->dmpi->stride[1];
+ mpi->stride[2]=vf->dmpi->stride[2];
+ }
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
+ // no DR, so get a new image! hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP,
+ MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+ mpi->width,mpi->height);
+ vf_clone_mpi_attributes(dmpi, mpi);
+ }else{
+ dmpi=vf->dmpi;
+ }
+
+ vf->priv->mpeg2= mpi->qscale_type;
+ if(vf->priv->log2_count || !(mpi->flags&MP_IMGFLAG_DIRECT)){
+ if(mpi->qscale || vf->priv->qp){
+ filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h, mpi->qscale, mpi->qstride);
+ }else{
+ memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
+ memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
+ }
+ }
+
+#if HAVE_MMX
+ if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
+#endif
+#if HAVE_MMX2
+ if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
+#endif
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+static void uninit(struct vf_instance *vf){
+ int i;
+ if(!vf->priv) return;
+
+ for(i=0; i<3; i++){
+ free(vf->priv->temp[i]);
+ vf->priv->temp[i]= NULL;
+ free(vf->priv->src[i]);
+ vf->priv->src[i]= NULL;
+ }
+ for(i=0; i<BLOCK*BLOCK; i++){
+ av_freep(&vf->priv->avctx_enc[i]);
+ }
+
+ free(vf->priv);
+ vf->priv=NULL;
+}
+
+//===========================================================================//
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt){
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ return vf_next_query_format(vf,fmt);
+ }
+ return 0;
+}
+
+static int control(struct vf_instance *vf, int request, void* data){
+ switch(request){
+ case VFCTRL_QUERY_MAX_PP_LEVEL:
+ return 8;
+ case VFCTRL_SET_PP_LEVEL:
+ vf->priv->log2_count= *((unsigned int*)data);
+ //FIXME we have to realloc a few things here
+ return CONTROL_TRUE;
+ }
+ return vf_next_control(vf,request,data);
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+
+ int log2c=-1;
+
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->get_image=get_image;
+ vf->query_format=query_format;
+ vf->uninit=uninit;
+ vf->control= control;
+ vf->priv=malloc(sizeof(struct vf_priv_s));
+ memset(vf->priv, 0, sizeof(struct vf_priv_s));
+
+ init_avcodec();
+
+ vf->priv->log2_count= 4;
+
+ if (args) sscanf(args, "%d:%d:%d", &log2c, &vf->priv->qp, &vf->priv->mode);
+
+ if( log2c >=0 && log2c <=8 )
+ vf->priv->log2_count = log2c;
+
+ if(vf->priv->qp < 0)
+ vf->priv->qp = 0;
+
+// #if HAVE_MMX
+// if(gCpuCaps.hasMMX){
+// store_slice= store_slice_mmx;
+// }
+// #endif
+
+ return 1;
+}
+
+const vf_info_t vf_info_uspp = {
+ "ultra simple/slow postprocess",
+ "uspp",
+ "Michael Niedermayer",
+ "",
+ vf_open,
+ NULL
+};
diff --git a/libavfilter/libmpcodecs/vf_yuvcsp.c b/libavfilter/libmpcodecs/vf_yuvcsp.c
new file mode 100644
index 0000000000..102ce14538
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_yuvcsp.c
@@ -0,0 +1,120 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+struct vf_priv_s {
+ int csp;
+};
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+ return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
+}
+
+static inline int clamp_y(int x){
+ return (x > 235) ? 235 : (x < 16) ? 16 : x;
+}
+
+static inline int clamp_c(int x){
+ return (x > 240) ? 240 : (x < 16) ? 16 : x;
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ int i,j;
+ uint8_t *y_in, *cb_in, *cr_in;
+ uint8_t *y_out, *cb_out, *cr_out;
+
+ vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
+ mpi->width, mpi->height);
+
+ y_in = mpi->planes[0];
+ cb_in = mpi->planes[1];
+ cr_in = mpi->planes[2];
+
+ y_out = vf->dmpi->planes[0];
+ cb_out = vf->dmpi->planes[1];
+ cr_out = vf->dmpi->planes[2];
+
+ for (i = 0; i < mpi->height; i++)
+ for (j = 0; j < mpi->width; j++)
+ y_out[i*vf->dmpi->stride[0]+j] = clamp_y(y_in[i*mpi->stride[0]+j]);
+
+ for (i = 0; i < mpi->chroma_height; i++)
+ for (j = 0; j < mpi->chroma_width; j++)
+ {
+ cb_out[i*vf->dmpi->stride[1]+j] = clamp_c(cb_in[i*mpi->stride[1]+j]);
+ cr_out[i*vf->dmpi->stride[2]+j] = clamp_c(cr_in[i*mpi->stride[2]+j]);
+ }
+
+ return vf_next_put_image(vf,vf->dmpi, pts);
+}
+
+//===========================================================================//
+
+/*
+static void uninit(struct vf_instance *vf){
+ free(vf->priv);
+}
+*/
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ switch(fmt){
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ return 1;
+ }
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+// vf->uninit=uninit;
+ vf->query_format=query_format;
+// vf->priv=calloc(1, sizeof(struct vf_priv_s));
+// if (args)
+// vf->priv->csp = atoi(args);
+ return 1;
+}
+
+const vf_info_t vf_info_yuvcsp = {
+ "yuv colorspace converter",
+ "yuvcsp",
+ "Alex Beregszaszi",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vf_yvu9.c b/libavfilter/libmpcodecs/vf_yvu9.c
new file mode 100644
index 0000000000..1f74261ccf
--- /dev/null
+++ b/libavfilter/libmpcodecs/vf_yvu9.c
@@ -0,0 +1,105 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+#include "libvo/fastmemcpy.h"
+
+//===========================================================================//
+
+static int config(struct vf_instance *vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt){
+
+ if(vf_next_query_format(vf,IMGFMT_YV12)<=0){
+ mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_WarnNextFilterDoesntSupport, "YVU9");
+ return 0;
+ }
+
+ return vf_next_config(vf,width,height,d_width,d_height,flags,IMGFMT_YV12);
+}
+
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+ mp_image_t *dmpi;
+ int y,w,h;
+
+ // hope we'll get DR buffer:
+ dmpi=vf_get_image(vf->next,IMGFMT_YV12,
+ MP_IMGTYPE_TEMP, 0/*MP_IMGFLAG_ACCEPT_STRIDE*/,
+ mpi->w, mpi->h);
+
+ for(y=0;y<mpi->h;y++)
+ fast_memcpy(dmpi->planes[0]+dmpi->stride[0]*y,
+ mpi->planes[0]+mpi->stride[0]*y,
+ mpi->w);
+
+ w=mpi->w/4; h=mpi->h/2;
+ for(y=0;y<h;y++){
+ unsigned char* s=mpi->planes[1]+mpi->stride[1]*(y>>1);
+ unsigned char* d=dmpi->planes[1]+dmpi->stride[1]*y;
+ int x;
+ for(x=0;x<w;x++) d[2*x]=d[2*x+1]=s[x];
+ }
+ for(y=0;y<h;y++){
+ unsigned char* s=mpi->planes[2]+mpi->stride[2]*(y>>1);
+ unsigned char* d=dmpi->planes[2]+dmpi->stride[2]*y;
+ int x;
+ for(x=0;x<w;x++) d[2*x]=d[2*x+1]=s[x];
+ }
+
+ vf_clone_mpi_attributes(dmpi, mpi);
+
+ return vf_next_put_image(vf,dmpi, pts);
+}
+
+//===========================================================================//
+
+static int query_format(struct vf_instance *vf, unsigned int fmt){
+ if (fmt == IMGFMT_YVU9 || fmt == IMGFMT_IF09)
+ return vf_next_query_format(vf,IMGFMT_YV12) & (~VFCAP_CSP_SUPPORTED_BY_HW);
+ return 0;
+}
+
+static int vf_open(vf_instance_t *vf, char *args){
+ vf->config=config;
+ vf->put_image=put_image;
+ vf->query_format=query_format;
+ return 1;
+}
+
+const vf_info_t vf_info_yvu9 = {
+ "fast YVU9->YV12 conversion",
+ "yvu9",
+ "alex",
+ "",
+ vf_open,
+ NULL
+};
+
+//===========================================================================//
diff --git a/libavfilter/libmpcodecs/vfcap.h b/libavfilter/libmpcodecs/vfcap.h
new file mode 100644
index 0000000000..611d642869
--- /dev/null
+++ b/libavfilter/libmpcodecs/vfcap.h
@@ -0,0 +1,56 @@
+/* VFCAP_* values: they are flags, returned by query_format():
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_VFCAP_H
+#define MPLAYER_VFCAP_H
+
+// set, if the given colorspace is supported (with or without conversion)
+#define VFCAP_CSP_SUPPORTED 0x1
+// set, if the given colorspace is supported _without_ conversion
+#define VFCAP_CSP_SUPPORTED_BY_HW 0x2
+// set if the driver/filter can draw OSD
+#define VFCAP_OSD 0x4
+// set if the driver/filter can handle compressed SPU stream
+#define VFCAP_SPU 0x8
+// scaling up/down by hardware, or software:
+#define VFCAP_HWSCALE_UP 0x10
+#define VFCAP_HWSCALE_DOWN 0x20
+#define VFCAP_SWSCALE 0x40
+// driver/filter can do vertical flip (upside-down)
+#define VFCAP_FLIP 0x80
+
+// driver/hardware handles timing (blocking)
+#define VFCAP_TIMER 0x100
+// driver _always_ flip image upside-down (for ve_vfw)
+#define VFCAP_FLIPPED 0x200
+// vf filter: accepts stride (put_image)
+// vo driver: has draw_slice() support for the given csp
+#define VFCAP_ACCEPT_STRIDE 0x400
+// filter does postprocessing (so you shouldn't scale/filter image before it)
+#define VFCAP_POSTPROC 0x800
+// filter cannot be reconfigured to different size & format
+#define VFCAP_CONSTANT 0x1000
+// filter can draw EOSD
+#define VFCAP_EOSD 0x2000
+// filter will draw EOSD at screen resolution (without scaling)
+#define VFCAP_EOSD_UNSCALED 0x4000
+// used by libvo and vf_vo, indicates the VO does not support draw_slice for this format
+#define VOCAP_NOSLICES 0x8000
+
+#endif /* MPLAYER_VFCAP_H */