diff options
-rw-r--r-- | MAINTAINERS | 9 | ||||
-rw-r--r-- | Makefile | 54 | ||||
-rwxr-xr-x | configure | 57 | ||||
-rw-r--r-- | doc/ffmpeg-doc.texi | 3 | ||||
-rw-r--r-- | doc/general.texi | 4 | ||||
-rw-r--r-- | doc/hooks.texi | 299 | ||||
-rw-r--r-- | ffmpeg.c | 38 | ||||
-rw-r--r-- | libavformat/Makefile | 2 | ||||
-rw-r--r-- | libavformat/framehook.c | 115 | ||||
-rw-r--r-- | libavformat/framehook.h | 52 | ||||
-rw-r--r-- | vhook/drawtext.c | 531 | ||||
-rw-r--r-- | vhook/fish.c | 382 | ||||
-rw-r--r-- | vhook/imlib2.c | 493 | ||||
-rw-r--r-- | vhook/null.c | 116 | ||||
-rw-r--r-- | vhook/ppm.c | 374 | ||||
-rw-r--r-- | vhook/watermark.c | 655 |
16 files changed, 7 insertions, 3177 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 73bf9dad68..845dd658a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18,15 +18,6 @@ Applications ffmpeg: ffmpeg.c Michael Niedermayer - Video Hooks: - vhook - vhook/watermark.c Marcus Engene - vhook/ppm.c - vhook/drawtext.c - vhook/fish.c - vhook/null.c - vhook/imlib2.c - ffplay: ffplay.c Michael Niedermayer @@ -32,10 +32,8 @@ FF_LDFLAGS := $(FFLDFLAGS) FF_EXTRALIBS := $(FFEXTRALIBS) FF_DEP_LIBS := $(DEP_LIBS) -ALL_TARGETS-$(CONFIG_VHOOK) += videohook ALL_TARGETS-$(BUILD_DOC) += documentation -INSTALL_TARGETS-$(CONFIG_VHOOK) += install-vhook ifneq ($(PROGS),) INSTALL_TARGETS-yes += install-progs install-data INSTALL_TARGETS-$(BUILD_DOC) += install-man @@ -81,41 +79,8 @@ cmdutils.o cmdutils.d: version.h alltools: $(addsuffix $(EXESUF),$(addprefix tools/, cws2fws pktdumper qt-faststart trasher)) -VHOOKCFLAGS += $(filter-out -mdynamic-no-pic,$(CFLAGS)) - -BASEHOOKS = fish null watermark -ALLHOOKS = $(BASEHOOKS) drawtext imlib2 ppm -ALLHOOKS_SRCS = $(addprefix vhook/, $(addsuffix .c, $(ALLHOOKS))) - -HOOKS-$(HAVE_FORK) += ppm -HOOKS-$(HAVE_IMLIB2) += imlib2 -HOOKS-$(HAVE_FREETYPE2) += drawtext - -HOOKS = $(addprefix vhook/, $(addsuffix $(SLIBSUF), $(BASEHOOKS) $(HOOKS-yes))) - -VHOOKCFLAGS-$(HAVE_IMLIB2) += `imlib2-config --cflags` -LIBS_imlib2$(SLIBSUF) = `imlib2-config --libs` - -VHOOKCFLAGS-$(HAVE_FREETYPE2) += `freetype-config --cflags` -LIBS_drawtext$(SLIBSUF) = `freetype-config --libs` - -VHOOKCFLAGS += $(VHOOKCFLAGS-yes) - -vhook/%.o vhook/%.d: CFLAGS:=$(VHOOKCFLAGS) - -# vhooks compile fine without libav*, but need them nonetheless. -videohook: $(FF_DEP_LIBS) $(HOOKS) - -$(eval VHOOKSHFLAGS=$(VHOOKSHFLAGS)) -vhook/%$(SLIBSUF): vhook/%.o - $(CC) $(LDFLAGS) -o $@ $(VHOOKSHFLAGS) $< $(VHOOKLIBS) $(LIBS_$(@F)) - -VHOOK_DEPS = $(HOOKS:$(SLIBSUF)=.d) -depend dep: $(VHOOK_DEPS) - documentation: $(addprefix doc/, ffmpeg-doc.html faq.html ffserver-doc.html \ - ffplay-doc.html general.html hooks.html \ - $(ALLMANPAGES)) + ffplay-doc.html general.html $(ALLMANPAGES)) doc/%.html: doc/%.texi texi2html -monolithic -number $< @@ -141,11 +106,7 @@ install-man: $(MANPAGES) install -d "$(MANDIR)/man1" install -m 644 $(MANPAGES) "$(MANDIR)/man1" -install-vhook: videohook - install -d "$(SHLIBDIR)/vhook" - install -m 755 $(HOOKS) "$(SHLIBDIR)/vhook" - -uninstall: uninstall-progs uninstall-data uninstall-man uninstall-vhook +uninstall: uninstall-progs uninstall-data uninstall-man uninstall-progs: rm -f $(addprefix "$(BINDIR)/", $(ALLPROGS)) @@ -156,10 +117,6 @@ uninstall-data: uninstall-man: rm -f $(addprefix "$(MANDIR)/man1/",$(ALLMANPAGES)) -uninstall-vhook: - rm -f $(addprefix "$(SHLIBDIR)/",$(ALLHOOKS_SRCS:.c=$(SLIBSUF))) - -rmdir "$(SHLIBDIR)/vhook/" - testclean: rm -rf tests/vsynth1 tests/vsynth2 tests/data tests/asynth1.sw tests/*~ @@ -168,10 +125,9 @@ clean:: testclean rm -f doc/*.html doc/*.pod doc/*.1 rm -f $(addprefix tests/,$(addsuffix $(EXESUF),audiogen videogen rotozoom seek_test tiny_psnr)) rm -f $(addprefix tools/,$(addsuffix $(EXESUF),cws2fws pktdumper qt-faststart trasher)) - rm -f vhook/*.o vhook/*~ vhook/*.so vhook/*.dylib vhook/*.dll distclean:: - rm -f version.h config.* vhook/*.d + rm -f version.h config.* # regression tests @@ -355,6 +311,4 @@ tests/seek_test$(EXESUF): tests/seek_test.c $(FF_DEP_LIBS) $(CC) $(FF_LDFLAGS) $(CFLAGS) -o $@ $< $(FF_EXTRALIBS) -.PHONY: lib videohook documentation *test regtest-* swscale-error zlib-error alltools check - --include $(VHOOK_DEPS) +.PHONY: lib documentation *test regtest-* swscale-error zlib-error alltools check @@ -82,9 +82,8 @@ show_help(){ echo " --disable-ffserver disable ffserver build" echo " --enable-postproc enable GPLed postprocessing support [no]" echo " --enable-swscale enable GPLed software scaler support [no]" - echo " --enable-avfilter video filter support (replaces vhook) [no]" + echo " --enable-avfilter video filter support [no]" echo " --enable-avfilter-lavf video filters dependent on avformat [no]" - echo " --disable-vhook disable video hooking support" echo " --enable-beosthreads use BeOS threads [no]" echo " --enable-os2threads use OS/2 threads [no]" echo " --enable-pthreads use pthreads [no]" @@ -799,7 +798,6 @@ CONFIG_LIST=" static swscale vdpau - vhook x11grab zlib " @@ -873,11 +871,9 @@ HAVE_LIST=" fast_cmov fast_unaligned fork - freetype2 gethrtime GetProcessTimes getrusage - imlib2 inet_aton inline_asm libdc1394_1 @@ -1133,7 +1129,6 @@ movie_filter_deps="avfilter_lavf" ffplay_deps="sdl" ffserver_deps="ffm_muxer rtp_protocol rtsp_demuxer" ffserver_extralibs='$ldl' -vhook_extralibs='$ldl' # default parameters @@ -1180,12 +1175,10 @@ enable optimizations enable protocols enable static enable stripping -vhook="default" # build settings add_cflags -D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 SHFLAGS='-shared -Wl,-soname,$$(@F)' -VHOOKSHFLAGS='$(SHFLAGS)' FFSERVERLDFLAGS=-Wl,-E LIBPREF="lib" LIBSUF=".a" @@ -1560,7 +1553,6 @@ case $target_os in darwin) disable need_memalign SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR) -Wl,-read_only_relocs,suppress' - VHOOKSHFLAGS='-dynamiclib -Wl,-single_module -flat_namespace -undefined suppress -Wl,-install_name,$(SHLIBDIR)/vhook/$$(@F)' strip="strip -x" FFLDFLAGS="-Wl,-dynamic,-search_paths_first" SLIBSUF=".dylib" @@ -1578,12 +1570,6 @@ case $target_os in LIBTARGET=x64 fi shlibdir_default="$bindir_default" - VHOOKSHFLAGS='-shared -L$(BUILD_ROOT)/libavformat -L$(BUILD_ROOT)/libavcodec -L$(BUILD_ROOT)/libavutil' - VHOOKLIBS='-lavformat$(BUILDSUF) -lavcodec$(BUILDSUF) -lavutil$(BUILDSUF) $(EXTRALIBS)' - if enabled swscale; then - VHOOKSHFLAGS="$VHOOKSHFLAGS -L\$(BUILD_ROOT)/libswscale" - VHOOKLIBS="$VHOOKLIBS -lswscale\$(BUILDSUF)" - fi disable ffserver SLIBPREF="" SLIBSUF=".dll" @@ -1607,12 +1593,6 @@ case $target_os in cygwin*) target_os=cygwin shlibdir_default="$bindir_default" - VHOOKSHFLAGS='-shared -L$(BUILD_ROOT)/libavformat -L$(BUILD_ROOT)/libavcodec -L$(BUILD_ROOT)/libavutil' - VHOOKLIBS='-lavformat$(BUILDSUF) -lavcodec$(BUILDSUF) -lavutil$(BUILDSUF) $(EXTRALIBS)' - if enabled swscale; then - VHOOKSHFLAGS="$VHOOKSHFLAGS -L\$(BUILD_ROOT)/libswscale" - VHOOKLIBS="$VHOOKLIBS -lswscale\$(BUILDSUF)" - fi SLIBPREF="cyg" SLIBSUF=".dll" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' @@ -1622,7 +1602,7 @@ case $target_os in enable dos_paths ;; *-dos|freedos|opendos) - disable ffplay ffserver vhook + disable ffplay ffserver disable $INDEV_LIST $OUTDEV_LIST network_extralibs="-lsocket" objformat="coff" @@ -1656,12 +1636,8 @@ case $target_os in emximp -o $(SUBDIR)$(LIBPREF)$(NAME)_dll.lib $(SUBDIR)$(NAME).def;' SLIB_INSTALL_EXTRA_CMD='install -m 644 $(SUBDIR)$(LIBPREF)$(NAME)_dll.a $(SUBDIR)$(LIBPREF)$(NAME)_dll.lib "$(LIBDIR)"' SLIB_UNINSTALL_EXTRA_CMD='rm -f "$(LIBDIR)"/$(LIBPREF)$(NAME)_dll.a "$(LIBDIR)"/$(LIBPREF)$(NAME)_dll.lib' - disable vhook enable dos_paths ;; - interix) - disable vhook - ;; *) die "Unknown OS '$target_os'." @@ -2040,24 +2016,6 @@ void foo(char * $restrict_keyword p); EOF done -test "$vhook" = "default" && vhook="$dlopen" - -if test "$target_os" = cygwin -o "$target_os" = mingw32 && enabled_all static vhook ; then - disable vhook - echo - echo "At the moment vhooks don't work on Cygwin or MinGW static builds." - echo "Patches welcome." - echo -fi - -if enabled vhook; then - check_ldflags -rdynamic - check_ldflags -export-dynamic -fi - -check_foo_config imlib2 imlib2 Imlib2.h imlib_load_font -check_foo_config freetype2 freetype ft2build.h FT_Init_FreeType - ########################################## # SDL check @@ -2225,8 +2183,6 @@ if enabled gprof; then add_ldflags -p fi -VHOOKCFLAGS="-fPIC" - # Find out if the .align argument is a power of two or not. check_asm asmalign_pot '".align 3"' @@ -2312,11 +2268,6 @@ echo "postprocessing support ${postproc-no}" echo "software scaler enabled ${swscale-no}" echo "new filter support ${avfilter-no}" echo "filters using lavformat ${avfilter_lavf-no}" -echo "video hooking ${vhook-no}" -if enabled vhook; then - echo "Imlib2 support ${imlib2-no}" - echo "FreeType support ${freetype2-no}" -fi echo "network support ${network-no}" if enabled network; then echo "IPv6 support ${ipv6-no}" @@ -2395,13 +2346,10 @@ enabled stripping && echo "STRIP=echo ignoring strip" >> config.mak echo "OPTFLAGS=$CFLAGS" >> config.mak -echo "VHOOKCFLAGS=$VHOOKCFLAGS" >> config.mak echo "LDFLAGS=$LDFLAGS" >> config.mak echo "FFSERVERLDFLAGS=$FFSERVERLDFLAGS" >> config.mak echo "SHFLAGS=$SHFLAGS" >> config.mak echo "YASMFLAGS=$YASMFLAGS" >> config.mak -echo "VHOOKSHFLAGS=$VHOOKSHFLAGS" >> config.mak -echo "VHOOKLIBS=$VHOOKLIBS" >> config.mak echo "LIBOBJFLAGS=$LIBOBJFLAGS" >> config.mak echo "BUILD_STATIC=$static" >> config.mak echo "BUILDSUF=$build_suffix" >> config.mak @@ -2529,7 +2477,6 @@ if enabled source_path_used; then libswscale \ tests \ tools \ - vhook \ " FILES="\ Makefile \ diff --git a/doc/ffmpeg-doc.texi b/doc/ffmpeg-doc.texi index e3f2dc8727..a217ef9ad4 100644 --- a/doc/ffmpeg-doc.texi +++ b/doc/ffmpeg-doc.texi @@ -660,9 +660,6 @@ Calculate PSNR of compressed frames. Dump video coding statistics to @file{vstats_HHMMSS.log}. @item -vstats_file @var{file} Dump video coding statistics to @var{file}. -@item -vhook @var{module} -Insert video processing @var{module}. @var{module} contains the module -name and its parameters separated by spaces. @item -top @var{n} top=1/bottom=0/auto=-1 field first @item -dc @var{precision} diff --git a/doc/general.texi b/doc/general.texi index 97a62bbe49..5f398f7482 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -691,10 +691,6 @@ Notes: @itemize -@item In order to compile vhooks, you must have a POSIX-compliant libdl in -your MinGW system. Get dlfcn-win32 from -@url{http://code.google.com/p/dlfcn-win32}. - @item In order to compile FFplay, you must have the MinGW development library of SDL. Get it from @url{http://www.libsdl.org}. Edit the @file{bin/sdl-config} script so that it points to the correct prefix diff --git a/doc/hooks.texi b/doc/hooks.texi deleted file mode 100644 index c410f1cb05..0000000000 --- a/doc/hooks.texi +++ /dev/null @@ -1,299 +0,0 @@ -\input texinfo @c -*- texinfo -*- - -@settitle Video Hook Documentation -@titlepage -@sp 7 -@center @titlefont{Video Hook Documentation} -@sp 3 -@end titlepage - - -@chapter Introduction - -@var{Please be aware that vhook is deprecated, and hence its development is -frozen (bug fixes are still accepted). -The substitute will be 'libavfilter', the result of our 'Video Filter API' -Google Summer of Code project. You may monitor its progress by subscribing to -the ffmpeg-soc mailing list at -@url{http://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc}.} - -The video hook functionality is designed (mostly) for live video. It allows -the video to be modified or examined between the decoder and the encoder. - -Any number of hook modules can be placed inline, and they are run in the -order that they were specified on the ffmpeg command line. - -The video hook modules are provided for use as a base for your own modules, -and are described below. - -Modules are loaded using the -vhook option to ffmpeg. The value of this parameter -is a space separated list of arguments. The first is the module name, and the rest -are passed as arguments to the Configure function of the module. - -The modules are dynamic libraries: They have different suffixes (.so, .dll, .dylib) -depending on your platform. And your platform dictates if they need to be -somewhere in your PATH, or in your LD_LIBRARY_PATH. Otherwise you will need to -specify the full path of the vhook file that you are using. - -@section null.c - -This does nothing. Actually it converts the input image to RGB24 and then converts -it back again. This is meant as a sample that you can use to test your setup. - -@section fish.c - -This implements a 'fish detector'. Essentially it converts the image into HSV -space and tests whether more than a certain percentage of the pixels fall into -a specific HSV cuboid. If so, then the image is saved into a file for processing -by other bits of code. - -Why use HSV? It turns out that HSV cuboids represent a more compact range of -colors than would an RGB cuboid. - -@section imlib2.c - -This module implements a text overlay for a video image. Currently it -supports a fixed overlay or reading the text from a file. The string -is passed through strftime() so that it is easy to imprint the date and -time onto the image. - -This module depends on the external library imlib2, available on -Sourceforge, among other places, if it is not already installed on -your system. - -You may also overlay an image (even semi-transparent) like TV stations do. -You may move either the text or the image around your video to create -scrolling credits, for example. - -The font file used is looked for in a FONTPATH environment variable, and -prepended to the point size as a command line option and can be specified -with the full path to the font file, as in: -@example --F /usr/X11R6/lib/X11/fonts/TTF/VeraBd.ttf/20 -@end example -where 20 is the point size. - -You can specify the filename to read RGB color names from. If it is not -specified, these defaults are used: @file{/usr/share/X11/rgb.txt} and -@file{/usr/lib/X11/rgb.txt} - -Options: -@multitable @columnfractions .2 .8 -@item @option{-C <rgb.txt>} @tab The filename to read RGB color names from -@item @option{-c <color>} @tab The color of the text -@item @option{-F <fontname>} @tab The font face and size -@item @option{-t <text>} @tab The text -@item @option{-f <filename>} @tab The filename to read text from -@item @option{-x <expression>}@tab x coordinate of text or image -@item @option{-y <expression>}@tab y coordinate of text or image -@item @option{-i <filename>} @tab The filename to read a image from -@item @option{-R <expression>}@tab Value for R color -@item @option{-G <expression>}@tab Value for G color -@item @option{-B <expression>}@tab Value for B color -@item @option{-A <expression>}@tab Value for Alpha channel -@end multitable - -Expressions are functions of these variables: -@multitable @columnfractions .2 .8 -@item @var{N} @tab frame number (starting at zero) -@item @var{H} @tab frame height -@item @var{W} @tab frame width -@item @var{h} @tab image height -@item @var{w} @tab image width -@item @var{X} @tab previous x coordinate of text or image -@item @var{Y} @tab previous y coordinate of text or image -@end multitable - -You may also use the constants @var{PI}, @var{E}, and the math functions available at the -FFmpeg formula evaluator at (@url{ffmpeg-doc.html#SEC13}), except @var{bits2qp(bits)} -and @var{qp2bits(qp)}. - -Usage examples: - -@example - # Remember to set the path to your fonts - FONTPATH="/cygdrive/c/WINDOWS/Fonts/" - FONTPATH="$FONTPATH:/usr/share/imlib2/data/fonts/" - FONTPATH="$FONTPATH:/usr/X11R6/lib/X11/fonts/TTF/" - export FONTPATH - - # Bulb dancing in a Lissajous pattern - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.dll -x W*(0.5+0.25*sin(N/47*PI))-w/2 -y H*(0.5+0.50*cos(N/97*PI))-h/2 -i /usr/share/imlib2/data/images/bulb.png' \ - -acodec copy -sameq output.avi - - # Text scrolling - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.dll -c red -F Vera.ttf/20 -x 150+0.5*N -y 70+0.25*N -t Hello' \ - -acodec copy -sameq output.avi - - # Date and time stamp, security-camera style: - ffmpeg -r 29.97 -s 320x256 -f video4linux -i /dev/video0 \ - -vhook 'vhook/imlib2.so -x 0 -y 0 -i black-260x20.png' \ - -vhook 'vhook/imlib2.so -c white -F VeraBd.ttf/12 -x 0 -y 0 -t %A-%D-%T' \ - output.avi - - In this example the video is captured from the first video capture card as a - 320x256 AVI, and a black 260 by 20 pixel PNG image is placed in the upper - left corner, with the day, date and time overlaid on it in Vera Bold 12 - point font. A simple black PNG file 260 pixels wide and 20 pixels tall - was created in the GIMP for this purpose. - - # Scrolling credits from a text file - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.so -c white -F VeraBd.ttf/16 -x 100 -y -1.0*N -f credits.txt' \ - -sameq output.avi - - In this example, the text is stored in a file, and is positioned 100 - pixels from the left hand edge of the video. The text is scrolled from the - bottom up. Making the y factor positive will scroll from the top down. - Increasing the magnitude of the y factor makes the text scroll faster, - decreasing it makes it scroll slower. Hint: Blank lines containing only - a newline are treated as end-of-file. To create blank lines, use lines - that consist of space characters only. - - # Scrolling credits with custom color from a text file - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.so -C rgb.txt -c CustomColor1 -F VeraBd.ttf/16 -x 100 -y -1.0*N -f credits.txt' \ - -sameq output.avi - - This example does the same as the one above, but specifies an rgb.txt file - to be used, which has a custom-made color in it. - - # Variable colors - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.so -t Hello -R abs(255*sin(N/47*PI)) -G abs(255*sin(N/47*PI)) -B abs(255*sin(N/47*PI))' \ - -sameq output.avi - - In this example, the color for the text goes up and down from black to - white. - - # Text fade-out - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.so -t Hello -A max(0,255-exp(N/47))' \ - -sameq output.avi - - In this example, the text fades out in about 10 seconds for a 25 fps input - video file. - - # scrolling credits from a graphics file - ffmpeg -sameq -i input.avi \ - -vhook 'vhook/imlib2.so -x 0 -y -1.0*N -i credits.png' output.avi - - In this example, a transparent PNG file the same width as the video - (e.g. 320 pixels), but very long, (e.g. 3000 pixels), was created, and - text, graphics, brushstrokes, etc, were added to the image. The image - is then scrolled up, from the bottom of the frame. - -@end example - -@section ppm.c - -It's basically a launch point for a PPM pipe, so you can use any -executable (or script) which consumes a PPM on stdin and produces a PPM -on stdout (and flushes each frame). The Netpbm utilities are a series of -such programs. - -A list of them is here: - -@url{http://netpbm.sourceforge.net/doc/directory.html} - -Usage example: - -@example -ffmpeg -i input -vhook "/path/to/ppm.so some-ppm-filter args" output -@end example - -@section drawtext.c - -This module implements a text overlay for a video image. Currently it -supports a fixed overlay or reading the text from a file. The string -is passed through strftime() so that it is easy to imprint the date and -time onto the image. - -Features: -@itemize @minus -@item TrueType, Type1 and others via the FreeType2 library -@item Font kerning (better output) -@item Line Wrap (put the text that doesn't fit one line on the next line) -@item Background box (currently in development) -@item Outline -@end itemize - -Options: -@multitable @columnfractions .2 .8 -@item @option{-c <color>} @tab Foreground color of the text ('internet' way) <#RRGGBB> [default #FFFFFF] -@item @option{-C <color>} @tab Background color of the text ('internet' way) <#RRGGBB> [default #000000] -@item @option{-f <font-filename>} @tab font file to use -@item @option{-t <text>} @tab text to display -@item @option{-T <filename>} @tab file to read text from -@item @option{-x <pos>} @tab x coordinate of the start of the text -@item @option{-y <pos>} @tab y coordinate of the start of the text -@end multitable - -Text fonts are being looked for in a FONTPATH environment variable. -If the FONTPATH environment variable is not available, or is not checked by -your target (i.e. Cygwin), then specify the full path to the font file as in: -@example --f /usr/X11R6/lib/X11/fonts/TTF/VeraBd.ttf -@end example - -Usage Example: -@example - # Remember to set the path to your fonts - FONTPATH="/cygdrive/c/WINDOWS/Fonts/" - FONTPATH="$FONTPATH:/usr/share/imlib2/data/fonts/" - FONTPATH="$FONTPATH:/usr/X11R6/lib/X11/fonts/TTF/" - export FONTPATH - - # Time and date display - ffmpeg -f video4linux2 -i /dev/video0 \ - -vhook 'vhook/drawtext.so -f VeraBd.ttf -t %A-%D-%T' movie.mpg - - This example grabs video from the first capture card and outputs it to an - MPEG video, and places "Weekday-dd/mm/yy-hh:mm:ss" at the top left of the - frame, updated every second, using the Vera Bold TrueType Font, which - should exist in: /usr/X11R6/lib/X11/fonts/TTF/ -@end example - -Check the man page for strftime() for all the various ways you can format -the date and time. - -@section watermark.c - -Command Line options: -@multitable @columnfractions .2 .8 -@item @option{-m [0|1]} @tab Mode (default: 0, see below) -@item @option{-t 000000 - FFFFFF} @tab Threshold, six digit hex number -@item @option{-f <filename>} @tab Watermark image filename, must be specified! -@end multitable - -MODE 0: - The watermark picture works like this (assuming color intensities 0..0xFF): - Per color do this: - If mask color is 0x80, no change to the original frame. - If mask color is < 0x80 the absolute difference is subtracted from the - frame. If result < 0, result = 0. - If mask color is > 0x80 the absolute difference is added to the - frame. If result > 0xFF, result = 0xFF. - - You can override the 0x80 level with the -t flag. E.g. if threshold is - 000000 the color value of watermark is added to the destination. - - This way a mask that is visible both in light and dark pictures can be made - (e.g. by using a picture generated by the Gimp and the bump map tool). - - An example watermark file is at: - @url{http://engene.se/ffmpeg_watermark.gif} - -MODE 1: - Per color do this: - If mask color > threshold color then the watermark pixel is used. - -Example usage: -@example - ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif' -an out.mov - ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif -m 1 -t 222222' -an out.mov -@end example - -@bye @@ -34,7 +34,6 @@ #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" -#include "libavformat/framehook.h" #include "libavcodec/opt.h" #include "libavcodec/audioconvert.h" #include "libavutil/fifo.h" @@ -203,7 +202,6 @@ static int audio_volume = 256; static int exit_on_error = 0; static int using_stdin = 0; -static int using_vhook = 0; static int verbose = 1; static int thread_count= 1; static int q_pressed = 0; @@ -736,7 +734,7 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void dec = ist->st->codec; /* deinterlace : must be done before any resize */ - if (do_deinterlace || using_vhook) { + if (do_deinterlace) { int size; /* create temporary picture */ @@ -764,10 +762,6 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void picture2 = picture; } - if (CONFIG_VHOOK) - frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height, - 1000000 * ist->pts / AV_TIME_BASE); - if (picture != picture2) *picture = *picture2; *bufp = buf; @@ -1772,10 +1766,6 @@ static int av_encode(AVFormatContext **output_files, codec->block_align= 0; break; case CODEC_TYPE_VIDEO: - if(using_vhook) { - fprintf(stderr,"-vcodec copy and -vhook are incompatible (frames are not decoded)\n"); - av_exit(1); - } codec->pix_fmt = icodec->pix_fmt; codec->width = icodec->width; codec->height = icodec->height; @@ -2651,29 +2641,6 @@ static void opt_video_tag(const char *arg) video_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24); } -#if CONFIG_VHOOK -static void add_frame_hooker(const char *arg) -{ - int argc = 0; - char *argv[64]; - int i; - char *args = av_strdup(arg); - - using_vhook = 1; - - argv[0] = strtok(args, " "); - while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) { - } - - i = frame_hook_add(argc, argv); - - if (i != 0) { - fprintf(stderr, "Failed to add video hook function: %s\n", arg); - av_exit(1); - } -} -#endif - static void opt_video_codec(const char *arg) { opt_codec(&video_stream_copy, &video_codec_name, CODEC_TYPE_VIDEO, arg); @@ -3840,9 +3807,6 @@ static const OptionDef options[] = { { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" }, { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" }, { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" }, -#if CONFIG_VHOOK - { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" }, -#endif { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" }, { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" }, { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" }, diff --git a/libavformat/Makefile b/libavformat/Makefile index b01fbbfeac..e3f59b2a01 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -228,8 +228,6 @@ OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o OBJS-$(CONFIG_LIBNUT_DEMUXER) += libnut.o riff.o OBJS-$(CONFIG_LIBNUT_MUXER) += libnut.o riff.o -OBJS-$(CONFIG_VHOOK) += framehook.o - # protocols I/O OBJS+= avio.o aviobuf.o diff --git a/libavformat/framehook.c b/libavformat/framehook.c deleted file mode 100644 index 494b30b5b1..0000000000 --- a/libavformat/framehook.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Video processing hooks - * Copyright (c) 2000, 2001 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include <errno.h> -#include "config.h" -#include "avformat.h" -#include "framehook.h" - -#if HAVE_DLFCN_H -#include <dlfcn.h> -#endif - - -typedef struct FrameHookEntry { - struct FrameHookEntry *next; - FrameHookConfigureFn Configure; - FrameHookProcessFn Process; - FrameHookReleaseFn Release; - void *ctx; -} FrameHookEntry; - -static FrameHookEntry *first_hook; - -/* Returns 0 on OK */ -int frame_hook_add(int argc, char *argv[]) -{ - void *loaded; - FrameHookEntry *fhe, **fhep; - - if (argc < 1) { - return ENOENT; - } - - loaded = dlopen(argv[0], RTLD_NOW); - if (!loaded) { - av_log(NULL, AV_LOG_ERROR, "%s\n", dlerror()); - return -1; - } - - fhe = av_mallocz(sizeof(*fhe)); - if (!fhe) { - return AVERROR(ENOMEM); - } - - fhe->Configure = dlsym(loaded, "Configure"); - fhe->Process = dlsym(loaded, "Process"); - fhe->Release = dlsym(loaded, "Release"); /* Optional */ - - if (!fhe->Process) { - av_log(NULL, AV_LOG_ERROR, "Failed to find Process entrypoint in %s\n", argv[0]); - return AVERROR(ENOENT); - } - - if (!fhe->Configure && argc > 1) { - av_log(NULL, AV_LOG_ERROR, "Failed to find Configure entrypoint in %s\n", argv[0]); - return AVERROR(ENOENT); - } - - if (argc > 1 || fhe->Configure) { - if (fhe->Configure(&fhe->ctx, argc, argv)) { - av_log(NULL, AV_LOG_ERROR, "Failed to Configure %s\n", argv[0]); - return AVERROR(EINVAL); - } - } - - for (fhep = &first_hook; *fhep; fhep = &((*fhep)->next)) { - } - - *fhep = fhe; - - return 0; -} - -void frame_hook_process(AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts) -{ - if (first_hook) { - FrameHookEntry *fhe; - - for (fhe = first_hook; fhe; fhe = fhe->next) { - fhe->Process(fhe->ctx, pict, pix_fmt, width, height, pts); - } - } -} - -void frame_hook_release(void) -{ - FrameHookEntry *fhe; - FrameHookEntry *fhenext; - - for (fhe = first_hook; fhe; fhe = fhenext) { - fhenext = fhe->next; - if (fhe->Release) - fhe->Release(fhe->ctx); - av_free(fhe); - } - - first_hook = NULL; -} diff --git a/libavformat/framehook.h b/libavformat/framehook.h deleted file mode 100644 index 0bad6067ac..0000000000 --- a/libavformat/framehook.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * video processing hooks - * copyright (c) 2000, 2001 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFORMAT_FRAMEHOOK_H -#define AVFORMAT_FRAMEHOOK_H - -#warning VHOOK is deprecated. Please help finishing libavfilter instead of wasting your time writing new filters for this crappy filter system. - -/* - * Prototypes for interface to .so that implement a video processing hook - */ - -#include "libavcodec/avcodec.h" - -/* Function must be called 'Configure' */ -typedef int (FrameHookConfigure)(void **ctxp, int argc, char *argv[]); -typedef FrameHookConfigure *FrameHookConfigureFn; -extern FrameHookConfigure Configure; - -/* Function must be called 'Process' */ -typedef void (FrameHookProcess)(void *ctx, struct AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts); -typedef FrameHookProcess *FrameHookProcessFn; -extern FrameHookProcess Process; - -/* Function must be called 'Release' */ -typedef void (FrameHookRelease)(void *ctx); -typedef FrameHookRelease *FrameHookReleaseFn; -extern FrameHookRelease Release; - -int frame_hook_add(int argc, char *argv[]); -void frame_hook_process(struct AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts); -void frame_hook_release(void); - -#endif /* AVFORMAT_FRAMEHOOK_H */ diff --git a/vhook/drawtext.c b/vhook/drawtext.c deleted file mode 100644 index 8638d60e07..0000000000 --- a/vhook/drawtext.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * drawtext.c: print text over the screen - ****************************************************************************** - * Options: - * -f <filename> font filename (MANDATORY!!!) - * -s <pixel_size> font size in pixels [default 16] - * -b print background - * -o outline glyphs (use the bg color) - * -x <pos> x position ( >= 0) [default 0] - * -y <pos> y position ( >= 0) [default 0] - * -t <text> text to print (will be passed to strftime()) - * MANDATORY: will be used even when -T is used. - * in this case, -t will be used if some error - * occurs - * -T <filename> file with the text (re-read every frame) - * -c <#RRGGBB> foreground color ('internet' way) [default #ffffff] - * -C <#RRGGBB> background color ('internet' way) [default #000000] - * - ****************************************************************************** - * Features: - * - True Type, Type1 and others via FreeType2 library - * - Font kerning (better output) - * - Line Wrap (if the text doesn't fit, the next char go to the next line) - * - Background box - * - Outline - ****************************************************************************** - * Author: Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br> - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define MAXSIZE_TEXT 1024 - -#include "libavformat/framehook.h" - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> -#undef time -#include <sys/time.h> -#include <time.h> - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_GLYPH_H - -#define SCALEBITS 10 -#define ONE_HALF (1 << (SCALEBITS - 1)) -#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5)) - -#define RGB_TO_YUV(rgb_color, yuv_color) do { \ - yuv_color[0] = (FIX(0.29900) * rgb_color[0] + FIX(0.58700) * rgb_color[1] + FIX(0.11400) * rgb_color[2] + ONE_HALF) >> SCALEBITS; \ - yuv_color[2] = ((FIX(0.50000) * rgb_color[0] - FIX(0.41869) * rgb_color[1] - FIX(0.08131) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \ - yuv_color[1] = ((- FIX(0.16874) * rgb_color[0] - FIX(0.33126) * rgb_color[1] + FIX(0.50000) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \ -} while (0) - -#define COPY_3(dst,src) { \ - dst[0]=src[0]; \ - dst[1]=src[1]; \ - dst[2]=src[2]; \ -} - - - -#define SET_PIXEL(picture, yuv_color, x, y) { \ - picture->data[0][ (x) + (y)*picture->linesize[0] ] = yuv_color[0]; \ - picture->data[1][ ((x/2) + (y/2)*picture->linesize[1]) ] = yuv_color[1]; \ - picture->data[2][ ((x/2) + (y/2)*picture->linesize[2]) ] = yuv_color[2]; \ -} - -#define GET_PIXEL(picture, yuv_color, x, y) { \ - yuv_color[0] = picture->data[0][ (x) + (y)*picture->linesize[0] ]; \ - yuv_color[1] = picture->data[1][ (x/2) + (y/2)*picture->linesize[1] ]; \ - yuv_color[2] = picture->data[2][ (x/2) + (y/2)*picture->linesize[2] ]; \ -} - - -typedef struct { - unsigned char *text; - char *file; - unsigned int x; - unsigned int y; - int bg; - int outline; - unsigned char bgcolor[3]; /* YUV */ - unsigned char fgcolor[3]; /* YUV */ - FT_Library library; - FT_Face face; - FT_Glyph glyphs[ 255 ]; - FT_Bitmap bitmaps[ 255 ]; - int advance[ 255 ]; - int bitmap_left[ 255 ]; - int bitmap_top[ 255 ]; - unsigned int glyphs_index[ 255 ]; - int text_height; - int baseline; - int use_kerning; -} ContextInfo; - - -void Release(void *ctx) -{ - if (ctx) - av_free(ctx); -} - - -static int ParseColor(char *text, unsigned char yuv_color[3]) -{ - char tmp[3]; - unsigned char rgb_color[3]; - int i; - - tmp[2] = '\0'; - - if ((!text) || (strlen(text) != 7) || (text[0] != '#') ) - return -1; - - for (i=0; i < 3; i++) - { - tmp[0] = text[i*2+1]; - tmp[1] = text[i*2+2]; - - rgb_color[i] = strtol(tmp, NULL, 16); - } - - RGB_TO_YUV(rgb_color, yuv_color); - - return 0; -} - -int Configure(void **ctxp, int argc, char *argv[]) -{ - int c; - int error; - ContextInfo *ci=NULL; - char *font=NULL; - unsigned int size=16; - FT_BBox bbox; - int yMax, yMin; - *ctxp = av_mallocz(sizeof(ContextInfo)); - ci = (ContextInfo *) *ctxp; - - /* configure Context Info */ - ci->text = NULL; - ci->file = NULL; - ci->x = ci->y = 0; - ci->fgcolor[0]=255; - ci->fgcolor[1]=128; - ci->fgcolor[2]=128; - ci->bgcolor[0]=0; - ci->fgcolor[1]=128; - ci->fgcolor[2]=128; - ci->bg = 0; - ci->outline = 0; - ci->text_height = 0; - - optind = 1; - while ((c = getopt(argc, argv, "f:t:T:x:y:s:c:C:bo")) > 0) { - switch (c) { - case 'f': - font = optarg; - break; - case 't': - ci->text = av_strdup(optarg); - break; - case 'T': - ci->file = av_strdup(optarg); - break; - case 'x': - ci->x = (unsigned int) atoi(optarg); - break; - case 'y': - ci->y = (unsigned int) atoi(optarg); - break; - case 's': - size = (unsigned int) atoi(optarg); - break; - case 'c': - if (ParseColor(optarg, ci->fgcolor) == -1) - { - av_log(NULL, AV_LOG_ERROR, "Invalid foreground color: '%s'. You must specify the color in the internet way(packaged hex): #RRGGBB, ie: -c #ffffff (for white foreground)\n", optarg); - return -1; - } - break; - case 'C': - if (ParseColor(optarg, ci->bgcolor) == -1) - { - av_log(NULL, AV_LOG_ERROR, "Invalid background color: '%s'. You must specify the color in the internet way(packaged hex): #RRGGBB, ie: -C #ffffff (for white background)\n", optarg); - return -1; - } - break; - case 'b': - ci->bg=1; - break; - case 'o': - ci->outline=1; - break; - case '?': - av_log(NULL, AV_LOG_ERROR, "Unrecognized argument '%s'\n", argv[optind]); - return -1; - } - } - - if (!ci->text) - { - av_log(NULL, AV_LOG_ERROR, "No text provided (-t text)\n"); - return -1; - } - - if (ci->file) - { - FILE *fp; - if ((fp=fopen(ci->file, "r")) == NULL) - { - av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno)); - } - else - { - fclose(fp); - } - } - - if (!font) - { - av_log(NULL, AV_LOG_ERROR, "No font file provided! (-f filename)\n"); - return -1; - } - - if ((error = FT_Init_FreeType(&(ci->library))) != 0) - { - av_log(NULL, AV_LOG_ERROR, "Could not load FreeType (error# %d).\n", error); - return -1; - } - - if ((error = FT_New_Face( ci->library, font, 0, &(ci->face) )) != 0) - { - av_log(NULL, AV_LOG_ERROR, "Could not load face: %s (error# %d).\n", font, error); - return -1; - } - - if ((error = FT_Set_Pixel_Sizes( ci->face, 0, size)) != 0) - { - av_log(NULL, AV_LOG_ERROR, "Could not set font size to %d pixels (error# %d).\n", size, error); - return -1; - } - - ci->use_kerning = FT_HAS_KERNING(ci->face); - - /* load and cache glyphs */ - yMax = -32000; - yMin = 32000; - for (c=0; c < 256; c++) - { - /* Load char */ - error = FT_Load_Char( ci->face, (unsigned char) c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME ); - if (error) continue; /* ignore errors */ - - /* Save bitmap */ - ci->bitmaps[c] = ci->face->glyph->bitmap; - /* Save bitmap left */ - ci->bitmap_left[c] = ci->face->glyph->bitmap_left; - /* Save bitmap top */ - ci->bitmap_top[c] = ci->face->glyph->bitmap_top; - - /* Save advance */ - ci->advance[c] = ci->face->glyph->advance.x >> 6; - - /* Save glyph */ - error = FT_Get_Glyph( ci->face->glyph, &(ci->glyphs[c]) ); - /* Save glyph index */ - ci->glyphs_index[c] = FT_Get_Char_Index( ci->face, (unsigned char) c ); - - /* Measure text height to calculate text_height (or the maximum text height) */ - FT_Glyph_Get_CBox( ci->glyphs[ c ], ft_glyph_bbox_pixels, &bbox ); - if (bbox.yMax > yMax) - yMax = bbox.yMax; - if (bbox.yMin < yMin) - yMin = bbox.yMin; - - } - - ci->text_height = yMax - yMin; - ci->baseline = yMax; - - return 0; -} - - - - -static inline void draw_glyph(AVPicture *picture, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_fgcolor[3], unsigned char yuv_bgcolor[3], int outline) -{ - int r, c; - int spixel, dpixel[3], in_glyph=0; - - if (bitmap->pixel_mode == ft_pixel_mode_mono) - { - in_glyph = 0; - for (r=0; (r < bitmap->rows) && (r+y < height); r++) - { - for (c=0; (c < bitmap->width) && (c+x < width); c++) - { - /* pixel in the picture (destination) */ - GET_PIXEL(picture, dpixel, (c+x), (y+r)); - - /* pixel in the glyph bitmap (source) */ - spixel = bitmap->buffer[r*bitmap->pitch +c/8] & (0x80>>(c%8)); - - if (spixel) - COPY_3(dpixel, yuv_fgcolor); - - if (outline) - { - /* border detection: */ - if ( (!in_glyph) && (spixel) ) - /* left border detected */ - { - in_glyph = 1; - /* draw left pixel border */ - if (c-1 >= 0) - SET_PIXEL(picture, yuv_bgcolor, (c+x-1), (y+r)); - } - else if ( (in_glyph) && (!spixel) ) - /* right border detected */ - { - in_glyph = 0; - /* 'draw' right pixel border */ - COPY_3(dpixel, yuv_bgcolor); - } - - if (in_glyph) - /* see if we have a top/bottom border */ - { - /* top */ - if ( (r-1 >= 0) && (! bitmap->buffer[(r-1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) - /* we have a top border */ - SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r-1)); - - /* bottom */ - if ( (r+1 < height) && (! bitmap->buffer[(r+1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) - /* we have a bottom border */ - SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r+1)); - - } - } - - SET_PIXEL(picture, dpixel, (c+x), (y+r)); - } - } - } -} - - -static inline void draw_box(AVPicture *picture, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_color[3]) -{ - int i, j; - - for (j = 0; (j < height); j++) - for (i = 0; (i < width); i++) - { - SET_PIXEL(picture, yuv_color, (i+x), (y+j)); - } - -} - - - - -void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts) -{ - ContextInfo *ci = (ContextInfo *) ctx; - FT_Face face = ci->face; - FT_GlyphSlot slot = face->glyph; - unsigned char *text = ci->text; - unsigned char c; - int x = 0, y = 0, i=0, size=0; - unsigned char buff[MAXSIZE_TEXT]; - unsigned char tbuff[MAXSIZE_TEXT]; - time_t now = time(0); - int str_w, str_w_max; - FT_Vector pos[MAXSIZE_TEXT]; - FT_Vector delta; - - if (ci->file) - { - int fd = open(ci->file, O_RDONLY); - - if (fd < 0) - { - text = ci->text; - av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno)); - } - else - { - int l = read(fd, tbuff, sizeof(tbuff) - 1); - - if (l >= 0) - { - tbuff[l] = 0; - text = tbuff; - } - else - { - text = ci->text; - av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be read. Using text provided with -t switch: %s", strerror(errno)); - } - close(fd); - } - } - else - { - text = ci->text; - } - - strftime(buff, sizeof(buff), text, localtime(&now)); - - text = buff; - - size = strlen(text); - - - - - /* measure string size and save glyphs position*/ - str_w = str_w_max = 0; - x = ci->x; - y = ci->y; - for (i=0; i < size; i++) - { - c = text[i]; - - /* kerning */ - if ( (ci->use_kerning) && (i > 0) && (ci->glyphs_index[c]) ) - { - FT_Get_Kerning( ci->face, - ci->glyphs_index[ text[i-1] ], - ci->glyphs_index[c], - ft_kerning_default, - &delta ); - - x += delta.x >> 6; - } - - if (( (x + ci->advance[ c ]) >= width ) || ( c == '\n' )) - { - str_w = width - ci->x - 1; - - y += ci->text_height; - x = ci->x; - } - - - /* save position */ - pos[i].x = x + ci->bitmap_left[c]; - pos[i].y = y - ci->bitmap_top[c] + ci->baseline; - - - x += ci->advance[c]; - - - if (str_w > str_w_max) - str_w_max = str_w; - - } - - - - - if (ci->bg) - { - /* Check if it doesn't pass the limits */ - if ( str_w_max + ci->x >= width ) - str_w_max = width - ci->x - 1; - if ( y >= height ) - y = height - 1 - 2*ci->y; - - /* Draw Background */ - draw_box( picture, ci->x, ci->y, str_w_max, y - ci->y, ci->bgcolor ); - } - - - - /* Draw Glyphs */ - for (i=0; i < size; i++) - { - c = text[i]; - - if ( - ( (c == '_') && (text == ci->text) ) || /* skip '_' (consider as space) - IF text was specified in cmd line - (which doesn't like nested quotes) */ - ( c == '\n' ) /* Skip new line char, just go to new line */ - ) - continue; - - /* now, draw to our target surface */ - draw_glyph( picture, - &(ci->bitmaps[ c ]), - pos[i].x, - pos[i].y, - width, - height, - ci->fgcolor, - ci->bgcolor, - ci->outline ); - - /* increment pen position */ - x += slot->advance.x >> 6; - } - - -} - diff --git a/vhook/fish.c b/vhook/fish.c deleted file mode 100644 index 3806df32eb..0000000000 --- a/vhook/fish.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Fish Detector Hook - * Copyright (c) 2002 Philip Gladstone - * - * This file implements a fish detector. It is used to see when a - * goldfish passes in front of the camera. It does this by counting - * the number of input pixels that fall within a particular HSV - * range. - * - * It takes a multitude of arguments: - * - * -h <num>-<num> the range of H values that are fish - * -s <num>-<num> the range of S values that are fish - * -v <num>-<num> the range of V values that are fish - * -z zap all non-fish values to black - * -l <num> limit the number of saved files to <num> - * -i <num> only check frames every <num> seconds - * -t <num> the threshold for the amount of fish pixels (range 0-1) - * -d turn debugging on - * -D <directory> where to put the fish images - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdarg.h> -#include <string.h> -#include <time.h> -#include <stdio.h> -#include <dirent.h> - -#include "libavformat/avformat.h" -#include "libavformat/framehook.h" -#include "libavcodec/dsputil.h" -#include "libswscale/swscale.h" -#undef fprintf - -static int sws_flags = SWS_BICUBIC; - -#define SCALEBITS 10 -#define ONE_HALF (1 << (SCALEBITS - 1)) -#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5)) - -#define YUV_TO_RGB1_CCIR(cb1, cr1)\ -{\ - cb = (cb1) - 128;\ - cr = (cr1) - 128;\ - r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\ - g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \ - ONE_HALF;\ - b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\ -} - -#define YUV_TO_RGB2_CCIR(r, g, b, y1)\ -{\ - yt = ((y1) - 16) * FIX(255.0/219.0);\ - r = cm[(yt + r_add) >> SCALEBITS];\ - g = cm[(yt + g_add) >> SCALEBITS];\ - b = cm[(yt + b_add) >> SCALEBITS];\ -} - - - - -typedef struct { - int h; /* 0 .. 360 */ - int s; /* 0 .. 255 */ - int v; /* 0 .. 255 */ -} HSV; - -typedef struct { - int zapping; - int threshold; - HSV dark, bright; - char *dir; - int file_limit; - int debug; - int min_interval; - int64_t next_pts; - int inset; - int min_width; - struct SwsContext *toRGB_convert_ctx; -} ContextInfo; - -static void dorange(const char *s, int *first, int *second, int maxval) -{ - sscanf(s, "%d-%d", first, second); - if (*first > maxval) - *first = maxval; - if (*second > maxval) - *second = maxval; -} - -void Release(void *ctx) -{ - ContextInfo *ci; - ci = (ContextInfo *) ctx; - - if (ctx) { - sws_freeContext(ci->toRGB_convert_ctx); - av_free(ctx); - } -} - -int Configure(void **ctxp, int argc, char *argv[]) -{ - ContextInfo *ci; - int c; - - *ctxp = av_mallocz(sizeof(ContextInfo)); - ci = (ContextInfo *) *ctxp; - - optind = 1; - - ci->dir = av_strdup("/tmp"); - ci->threshold = 100; - ci->file_limit = 100; - ci->min_interval = 1000000; - ci->inset = 10; /* Percent */ - - while ((c = getopt(argc, argv, "w:i:dh:s:v:zl:t:D:")) > 0) { - switch (c) { - case 'h': - dorange(optarg, &ci->dark.h, &ci->bright.h, 360); - break; - case 's': - dorange(optarg, &ci->dark.s, &ci->bright.s, 255); - break; - case 'v': - dorange(optarg, &ci->dark.v, &ci->bright.v, 255); - break; - case 'z': - ci->zapping = 1; - break; - case 'l': - ci->file_limit = atoi(optarg); - break; - case 'i': - ci->min_interval = 1000000 * atof(optarg); - break; - case 't': - ci->threshold = atof(optarg) * 1000; - if (ci->threshold > 1000 || ci->threshold < 0) { - av_log(NULL, AV_LOG_ERROR, "Invalid threshold value '%s' (range is 0-1)\n", optarg); - return -1; - } - break; - case 'w': - ci->min_width = atoi(optarg); - break; - case 'd': - ci->debug++; - break; - case 'D': - ci->dir = av_strdup(optarg); - break; - default: - av_log(NULL, AV_LOG_ERROR, "Unrecognized argument '%s'\n", argv[optind]); - return -1; - } - } - - av_log(NULL, AV_LOG_INFO, "Fish detector configured:\n"); - av_log(NULL, AV_LOG_INFO, " HSV range: %d,%d,%d - %d,%d,%d\n", - ci->dark.h, - ci->dark.s, - ci->dark.v, - ci->bright.h, - ci->bright.s, - ci->bright.v); - av_log(NULL, AV_LOG_INFO, " Threshold is %d%% pixels\n", ci->threshold / 10); - - - return 0; -} - -static void get_hsv(HSV *hsv, int r, int g, int b) -{ - int i, v, x, f; - - x = (r < g) ? r : g; - if (b < x) - x = b; - v = (r > g) ? r : g; - if (b > v) - v = b; - - if (v == x) { - hsv->h = 0; - hsv->s = 0; - hsv->v = v; - return; - } - - if (r == v) { - f = g - b; - i = 0; - } else if (g == v) { - f = b - r; - i = 2 * 60; - } else { - f = r - g; - i = 4 * 60; - } - - hsv->h = i + (60 * f) / (v - x); - if (hsv->h < 0) - hsv->h += 360; - - hsv->s = (255 * (v - x)) / v; - hsv->v = v; - - return; -} - -void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts) -{ - ContextInfo *ci = (ContextInfo *) ctx; - uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; - int rowsize = picture->linesize[0]; - -#if 0 - av_log(NULL, AV_LOG_DEBUG, "pix_fmt = %d, width = %d, pts = %lld, ci->next_pts = %lld\n", - pix_fmt, width, pts, ci->next_pts); -#endif - - if (pts < ci->next_pts) - return; - - if (width < ci->min_width) - return; - - ci->next_pts = pts + 1000000; - - if (pix_fmt == PIX_FMT_YUV420P) { - uint8_t *y, *u, *v; - int width2 = width >> 1; - int inrange = 0; - int pixcnt; - int h; - int h_start, h_end; - int w_start, w_end; - - h_end = 2 * ((ci->inset * height) / 200); - h_start = height - h_end; - - w_end = (ci->inset * width2) / 100; - w_start = width2 - w_end; - - pixcnt = ((h_start - h_end) >> 1) * (w_start - w_end); - - y = picture->data[0] + h_end * picture->linesize[0] + w_end * 2; - u = picture->data[1] + h_end * picture->linesize[1] / 2 + w_end; - v = picture->data[2] + h_end * picture->linesize[2] / 2 + w_end; - - for (h = h_start; h > h_end; h -= 2) { - int w; - - for (w = w_start; w > w_end; w--) { - unsigned int r,g,b; - HSV hsv; - int cb, cr, yt, r_add, g_add, b_add; - - YUV_TO_RGB1_CCIR(u[0], v[0]); - YUV_TO_RGB2_CCIR(r, g, b, y[0]); - - get_hsv(&hsv, r, g, b); - - if (ci->debug > 1) - av_log(NULL, AV_LOG_DEBUG, "(%d,%d,%d) -> (%d,%d,%d)\n", - r,g,b,hsv.h,hsv.s,hsv.v); - - - if (hsv.h >= ci->dark.h && hsv.h <= ci->bright.h && - hsv.s >= ci->dark.s && hsv.s <= ci->bright.s && - hsv.v >= ci->dark.v && hsv.v <= ci->bright.v) { - inrange++; - } else if (ci->zapping) { - y[0] = y[1] = y[rowsize] = y[rowsize + 1] = 16; - u[0] = 128; - v[0] = 128; - } - - y+= 2; - u++; - v++; - } - - y += picture->linesize[0] * 2 - (w_start - w_end) * 2; - u += picture->linesize[1] - (w_start - w_end); - v += picture->linesize[2] - (w_start - w_end); - } - - if (ci->debug) - av_log(NULL, AV_LOG_INFO, "Fish: Inrange=%d of %d = %d threshold\n", inrange, pixcnt, 1000 * inrange / pixcnt); - - if (inrange * 1000 / pixcnt >= ci->threshold) { - /* Save to file */ - int size; - char *buf; - AVPicture picture1; - static int frame_counter; - static int foundfile; - - if ((frame_counter++ % 20) == 0) { - /* Check how many files we have */ - DIR *d; - - foundfile = 0; - - d = opendir(ci->dir); - if (d) { - struct dirent *dent; - - while ((dent = readdir(d))) { - if (strncmp("fishimg", dent->d_name, 7) == 0) { - if (strcmp(".ppm", dent->d_name + strlen(dent->d_name) - 4) == 0) { - foundfile++; - } - } - } - closedir(d); - } - } - - if (foundfile < ci->file_limit) { - FILE *f; - char fname[256]; - - size = avpicture_get_size(PIX_FMT_RGB24, width, height); - buf = av_malloc(size); - - avpicture_fill(&picture1, buf, PIX_FMT_RGB24, width, height); - - // if we already got a SWS context, let's realloc if is not re-useable - ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, - width, height, pix_fmt, - width, height, PIX_FMT_RGB24, - sws_flags, NULL, NULL, NULL); - if (ci->toRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the toRGB conversion context\n"); - return; - } - // img_convert parameters are 2 first destination, then 4 source - // sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->toRGB_convert_ctx, - picture->data, picture->linesize, 0, height, - picture1.data, picture1.linesize); - - /* Write out the PPM file */ - snprintf(fname, sizeof(fname), "%s/fishimg%ld_%"PRId64".ppm", ci->dir, (long)(av_gettime() / 1000000), pts); - f = fopen(fname, "w"); - if (f) { - fprintf(f, "P6 %d %d 255\n", width, height); - if (!fwrite(buf, width * height * 3, 1, f)) - av_log(ctx, AV_LOG_ERROR, "Couldn't write to PPM file %s\n", fname); - fclose(f); - } - - av_free(buf); - ci->next_pts = pts + ci->min_interval; - } - } - } -} - diff --git a/vhook/imlib2.c b/vhook/imlib2.c deleted file mode 100644 index ffe873c58e..0000000000 --- a/vhook/imlib2.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * imlib2 based hook - * Copyright (c) 2002 Philip Gladstone - * - * This module is very much intended as an example of what could be done. - * - * One caution is that this is an expensive process -- in particular the - * conversion of the image into RGB and back is time consuming. For some - * special cases -- e.g. painting black text -- it would be faster to paint - * the text into a bitmap and then combine it directly into the YUV - * image. However, this code is fast enough to handle 10 fps of 320x240 on a - * 900MHz Duron in maybe 15% of the CPU. - - * See further statistics on Pentium4, 3GHz, FFMpeg is SVN-r6798 - * Input movie is 20.2 seconds of PAL DV on AVI - * Output movie is DVD compliant VOB. - * - ffmpeg -i input.avi -target pal-dvd out.vob - # 13.516s just transcode - ffmpeg -i input.avi -vhook /usr/local/bin/vhook/null.dll -target pal-dvd out.vob - # 23.546s transcode and img_convert - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.dll -c red -F Vera/20 -x 150-0.5*N -y 70+0.25*N -t Hello_person' \ - -target pal-dvd out.vob - # 21.454s transcode, img_convert and move text around - ffmpeg -i input.avi -vhook \ - 'vhook/imlib2.dll -x 150-0.5*N -y 70+0.25*N -i /usr/share/imlib2/data/images/bulb.png' \ - -target pal-dvd out.vob - # 20.828s transcode, img_convert and move image around - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavformat/framehook.h" -#include "libswscale/swscale.h" - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <stdarg.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> -#undef time -#include <sys/time.h> -#include <time.h> -#include <Imlib2.h> -#include "libavcodec/eval.h" - -const char *const_names[]={ - "PI", - "E", - "N", // frame number (starting at zero) - "H", // frame height - "W", // frame width - "h", // image height - "w", // image width - "X", // previous x - "Y", // previous y - NULL -}; - -static int sws_flags = SWS_BICUBIC; - -typedef struct { - int dummy; - Imlib_Font fn; - char *text; - char *file; - int r, g, b, a; - AVEvalExpr *eval_r, *eval_g, *eval_b, *eval_a; - char *expr_R, *expr_G, *expr_B, *expr_A; - int eval_colors; - double x, y; - char *fileImage; - struct CachedImage *cache; - Imlib_Image imageOverlaid; - AVEvalExpr *eval_x, *eval_y; - char *expr_x, *expr_y; - int frame_number; - int imageOverlaid_width, imageOverlaid_height; - - // This vhook first converts frame to RGB ... - struct SwsContext *toRGB_convert_ctx; - // ... and then converts back frame from RGB to initial format - struct SwsContext *fromRGB_convert_ctx; -} ContextInfo; - -typedef struct CachedImage { - struct CachedImage *next; - Imlib_Image image; - int width; - int height; -} CachedImage; - -void Release(void *ctx) -{ - ContextInfo *ci; - ci = (ContextInfo *) ctx; - - if (ci->cache) { - imlib_context_set_image(ci->cache->image); - imlib_free_image(); - av_free(ci->cache); - } - if (ctx) { - if (ci->imageOverlaid) { - imlib_context_set_image(ci->imageOverlaid); - imlib_free_image(); - } - ff_eval_free(ci->eval_x); - ff_eval_free(ci->eval_y); - ff_eval_free(ci->eval_r); - ff_eval_free(ci->eval_g); - ff_eval_free(ci->eval_b); - ff_eval_free(ci->eval_a); - - av_free(ci->expr_x); - av_free(ci->expr_y); - av_free(ci->expr_R); - av_free(ci->expr_G); - av_free(ci->expr_B); - av_free(ci->expr_A); - sws_freeContext(ci->toRGB_convert_ctx); - sws_freeContext(ci->fromRGB_convert_ctx); - av_free(ctx); - } -} - -int Configure(void **ctxp, int argc, char *argv[]) -{ - int c; - ContextInfo *ci; - char *rgbtxt = 0; - const char *font = "LucidaSansDemiBold/16"; - char *fp = getenv("FONTPATH"); - char *color = 0; - FILE *f; - char *p; - const char *error; - - *ctxp = av_mallocz(sizeof(ContextInfo)); - ci = (ContextInfo *) *ctxp; - - ci->x = 0.0; - ci->y = 0.0; - ci->expr_x = "0.0"; - ci->expr_y = "0.0"; - - optind = 1; - - /* Use ':' to split FONTPATH */ - if (fp) - while ((p = strchr(fp, ':'))) { - *p = 0; - imlib_add_path_to_font_path(fp); - fp = p + 1; - } - if ((fp) && (*fp)) - imlib_add_path_to_font_path(fp); - - - while ((c = getopt(argc, argv, "R:G:B:A:C:c:f:F:t:x:y:i:")) > 0) { - switch (c) { - case 'R': - ci->expr_R = av_strdup(optarg); - ci->eval_colors = 1; - break; - case 'G': - ci->expr_G = av_strdup(optarg); - ci->eval_colors = 1; - break; - case 'B': - ci->expr_B = av_strdup(optarg); - ci->eval_colors = 1; - break; - case 'A': - ci->expr_A = av_strdup(optarg); - break; - case 'C': - rgbtxt = optarg; - break; - case 'c': - color = optarg; - break; - case 'F': - font = optarg; - break; - case 't': - ci->text = av_strdup(optarg); - break; - case 'f': - ci->file = av_strdup(optarg); - break; - case 'x': - ci->expr_x = av_strdup(optarg); - break; - case 'y': - ci->expr_y = av_strdup(optarg); - break; - case 'i': - ci->fileImage = av_strdup(optarg); - break; - case '?': - av_log(NULL, AV_LOG_ERROR, "Unrecognized argument '%s'\n", argv[optind]); - return -1; - } - } - - if (ci->eval_colors && !(ci->expr_R && ci->expr_G && ci->expr_B)) - { - av_log(NULL, AV_LOG_ERROR, "You must specify expressions for all or no colors.\n"); - return -1; - } - - if (ci->text || ci->file) { - ci->fn = imlib_load_font(font); - if (!ci->fn) { - av_log(NULL, AV_LOG_ERROR, "Failed to load font '%s'\n", font); - return -1; - } - imlib_context_set_font(ci->fn); - imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT); - } - - if (color) { - char buff[256]; - int done = 0; - - if (ci->eval_colors) - { - av_log(NULL, AV_LOG_ERROR, "You must not specify both a color name and expressions for the colors.\n"); - return -1; - } - - if (rgbtxt) - f = fopen(rgbtxt, "r"); - else - { - f = fopen("/usr/share/X11/rgb.txt", "r"); - if (!f) - f = fopen("/usr/lib/X11/rgb.txt", "r"); - } - if (!f) { - av_log(NULL, AV_LOG_ERROR, "Failed to find RGB color names file\n"); - return -1; - } - while (fgets(buff, sizeof(buff), f)) { - int r, g, b; - char colname[80]; - - if (sscanf(buff, "%d %d %d %64s", &r, &g, &b, colname) == 4 && - strcasecmp(colname, color) == 0) { - ci->r = r; - ci->g = g; - ci->b = b; - /* fprintf(stderr, "%s -> %d,%d,%d\n", colname, r, g, b); */ - done = 1; - break; - } - } - fclose(f); - if (!done) { - av_log(NULL, AV_LOG_ERROR, "Unable to find color '%s' in rgb.txt\n", color); - return -1; - } - } else if (ci->eval_colors) { - if (!(ci->eval_r = ff_parse(ci->expr_R, const_names, NULL, NULL, NULL, NULL, &error))){ - av_log(NULL, AV_LOG_ERROR, "Couldn't parse R expression '%s': %s\n", ci->expr_R, error); - return -1; - } - if (!(ci->eval_g = ff_parse(ci->expr_G, const_names, NULL, NULL, NULL, NULL, &error))){ - av_log(NULL, AV_LOG_ERROR, "Couldn't parse G expression '%s': %s\n", ci->expr_G, error); - return -1; - } - if (!(ci->eval_b = ff_parse(ci->expr_B, const_names, NULL, NULL, NULL, NULL, &error))){ - av_log(NULL, AV_LOG_ERROR, "Couldn't parse B expression '%s': %s\n", ci->expr_B, error); - return -1; - } - } - - if (ci->expr_A) { - if (!(ci->eval_a = ff_parse(ci->expr_A, const_names, NULL, NULL, NULL, NULL, &error))){ - av_log(NULL, AV_LOG_ERROR, "Couldn't parse A expression '%s': %s\n", ci->expr_A, error); - return -1; - } - } else { - ci->a = 255; - } - - if (!(ci->eval_colors || ci->eval_a)) - imlib_context_set_color(ci->r, ci->g, ci->b, ci->a); - - /* load the image (for example, credits for a movie) */ - if (ci->fileImage) { - ci->imageOverlaid = imlib_load_image_immediately(ci->fileImage); - if (!(ci->imageOverlaid)){ - av_log(NULL, AV_LOG_ERROR, "Couldn't load image '%s'\n", ci->fileImage); - return -1; - } - imlib_context_set_image(ci->imageOverlaid); - ci->imageOverlaid_width = imlib_image_get_width(); - ci->imageOverlaid_height = imlib_image_get_height(); - } - - if (!(ci->eval_x = ff_parse(ci->expr_x, const_names, NULL, NULL, NULL, NULL, &error))){ - av_log(NULL, AV_LOG_ERROR, "Couldn't parse x expression '%s': %s\n", ci->expr_x, error); - return -1; - } - - if (!(ci->eval_y = ff_parse(ci->expr_y, const_names, NULL, NULL, NULL, NULL, &error))){ - av_log(NULL, AV_LOG_ERROR, "Couldn't parse y expression '%s': %s\n", ci->expr_y, error); - return -1; - } - - return 0; -} - -static Imlib_Image get_cached_image(ContextInfo *ci, int width, int height) -{ - CachedImage *cache; - - for (cache = ci->cache; cache; cache = cache->next) { - if (width == cache->width && height == cache->height) - return cache->image; - } - - return NULL; -} - -static void put_cached_image(ContextInfo *ci, Imlib_Image image, int width, int height) -{ - CachedImage *cache = av_mallocz(sizeof(*cache)); - - cache->image = image; - cache->width = width; - cache->height = height; - cache->next = ci->cache; - ci->cache = cache; -} - -void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts) -{ - ContextInfo *ci = (ContextInfo *) ctx; - AVPicture picture1; - Imlib_Image image; - DATA32 *data; - - image = get_cached_image(ci, width, height); - - if (!image) { - image = imlib_create_image(width, height); - put_cached_image(ci, image, width, height); - } - - imlib_context_set_image(image); - data = imlib_image_get_data(); - - avpicture_fill(&picture1, (uint8_t *) data, PIX_FMT_RGB32, width, height); - - // if we already got a SWS context, let's realloc if is not re-useable - ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, - width, height, pix_fmt, - width, height, PIX_FMT_RGB32, - sws_flags, NULL, NULL, NULL); - if (ci->toRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the toRGB conversion context\n"); - return; - } - -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->toRGB_convert_ctx, - picture->data, picture->linesize, 0, height, - picture1.data, picture1.linesize); - - imlib_image_set_has_alpha(0); - - { - int wid, hig, h_a, v_a; - char buff[1000]; - char tbuff[1000]; - const char *tbp = ci->text; - time_t now = time(0); - char *p, *q; - int y; - - double const_values[]={ - M_PI, - M_E, - ci->frame_number, // frame number (starting at zero) - height, // frame height - width, // frame width - ci->imageOverlaid_height, // image height - ci->imageOverlaid_width, // image width - ci->x, // previous x - ci->y, // previous y - 0 - }; - - if (ci->file) { - int fd = open(ci->file, O_RDONLY); - - if (fd < 0) { - tbp = "[File not found]"; - } else { - int l = read(fd, tbuff, sizeof(tbuff) - 1); - - if (l >= 0) { - tbuff[l] = 0; - tbp = tbuff; - } else { - tbp = "[I/O Error]"; - } - close(fd); - } - } - - if (tbp) - strftime(buff, sizeof(buff), tbp, localtime(&now)); - else if (!(ci->imageOverlaid)) - strftime(buff, sizeof(buff), "[No data]", localtime(&now)); - - ci->x = ff_parse_eval(ci->eval_x, const_values, ci); - ci->y = ff_parse_eval(ci->eval_y, const_values, ci); - y = ci->y; - - if (ci->eval_a) { - ci->a = ff_parse_eval(ci->eval_a, const_values, ci); - } - - if (ci->eval_colors) { - ci->r = ff_parse_eval(ci->eval_r, const_values, ci); - ci->g = ff_parse_eval(ci->eval_g, const_values, ci); - ci->b = ff_parse_eval(ci->eval_b, const_values, ci); - } - - if (ci->eval_colors || ci->eval_a) { - imlib_context_set_color(ci->r, ci->g, ci->b, ci->a); - } - - if (!(ci->imageOverlaid)) - for (p = buff; p; p = q) { - q = strchr(p, '\n'); - if (q) - *q++ = 0; - - imlib_text_draw_with_return_metrics(ci->x, y, p, &wid, &hig, &h_a, &v_a); - y += v_a; - } - - if (ci->imageOverlaid) { - imlib_context_set_image(image); - imlib_blend_image_onto_image(ci->imageOverlaid, 0, - 0, 0, ci->imageOverlaid_width, ci->imageOverlaid_height, - ci->x, ci->y, ci->imageOverlaid_width, ci->imageOverlaid_height); - } - - } - - ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx, - width, height, PIX_FMT_RGB32, - width, height, pix_fmt, - sws_flags, NULL, NULL, NULL); - if (ci->fromRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the fromRGB conversion context\n"); - return; - } -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->fromRGB_convert_ctx, - picture1.data, picture1.linesize, 0, height, - picture->data, picture->linesize); - - ci->frame_number++; -} - diff --git a/vhook/null.c b/vhook/null.c deleted file mode 100644 index 1f957fbf5e..0000000000 --- a/vhook/null.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Null Video Hook - * Copyright (c) 2002 Philip Gladstone - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include <stdio.h> - -#include "libavformat/framehook.h" -#include "libswscale/swscale.h" - -static int sws_flags = SWS_BICUBIC; - -typedef struct { - int dummy; - - // This vhook first converts frame to RGB ... - struct SwsContext *toRGB_convert_ctx; - - // ... and later converts back frame from RGB to initial format - struct SwsContext *fromRGB_convert_ctx; - -} ContextInfo; - -void Release(void *ctx) -{ - ContextInfo *ci; - ci = (ContextInfo *) ctx; - - if (ctx) { - sws_freeContext(ci->toRGB_convert_ctx); - sws_freeContext(ci->fromRGB_convert_ctx); - av_free(ctx); - } -} - -int Configure(void **ctxp, int argc, char *argv[]) -{ - av_log(NULL, AV_LOG_DEBUG, "Called with argc=%d\n", argc); - - *ctxp = av_mallocz(sizeof(ContextInfo)); - return 0; -} - -void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts) -{ - ContextInfo *ci = (ContextInfo *) ctx; - char *buf = 0; - AVPicture picture1; - AVPicture *pict = picture; - - (void) ci; - - if (pix_fmt != PIX_FMT_RGB24) { - int size; - - size = avpicture_get_size(PIX_FMT_RGB24, width, height); - buf = av_malloc(size); - - avpicture_fill(&picture1, buf, PIX_FMT_RGB24, width, height); - - // if we already got a SWS context, let's realloc if is not re-useable - ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, - width, height, pix_fmt, - width, height, PIX_FMT_RGB24, - sws_flags, NULL, NULL, NULL); - if (ci->toRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the toRGB conversion context\n"); - return; - } -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->toRGB_convert_ctx, - picture->data, picture->linesize, 0, height, - picture1.data, picture1.linesize); - - pict = &picture1; - } - - /* Insert filter code here */ - - if (pix_fmt != PIX_FMT_RGB24) { - ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx, - width, height, PIX_FMT_RGB24, - width, height, pix_fmt, - sws_flags, NULL, NULL, NULL); - if (ci->fromRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the fromRGB conversion context\n"); - return; - } -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->fromRGB_convert_ctx, - picture1.data, picture1.linesize, 0, height, - picture->data, picture->linesize); - } - - av_free(buf); -} - diff --git a/vhook/ppm.c b/vhook/ppm.c deleted file mode 100644 index 86fad1dc59..0000000000 --- a/vhook/ppm.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * PPM Video Hook - * Copyright (c) 2003 Charles Yates - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <ctype.h> -#include "libavutil/avstring.h" -#include "libavformat/framehook.h" -#include "libavformat/avformat.h" -#include "libswscale/swscale.h" -#undef fprintf - -static int sws_flags = SWS_BICUBIC; - -/** Bi-directional pipe structure. -*/ - -typedef struct rwpipe -{ - int pid; - FILE *reader; - FILE *writer; -} -rwpipe; - -/** Create a bidirectional pipe for the given command. -*/ - -static rwpipe *rwpipe_open( int argc, char *argv[] ) -{ - rwpipe *this = av_mallocz( sizeof( rwpipe ) ); - - if ( this != NULL ) - { - int input[ 2 ]; - int output[ 2 ]; - - if (!pipe( input )) - return NULL; - - if (!pipe( output )) - return NULL; - - this->pid = fork(); - - if ( this->pid == 0 ) - { -#define COMMAND_SIZE 10240 - char *command = av_mallocz( COMMAND_SIZE ); - int i; - - strcpy( command, "" ); - for ( i = 0; i < argc; i ++ ) - { - av_strlcat( command, argv[ i ], COMMAND_SIZE ); - av_strlcat( command, " ", COMMAND_SIZE ); - } - - dup2( output[ 0 ], STDIN_FILENO ); - dup2( input[ 1 ], STDOUT_FILENO ); - - close( input[ 0 ] ); - close( input[ 1 ] ); - close( output[ 0 ] ); - close( output[ 1 ] ); - - execl("/bin/sh", "sh", "-c", command, (char*)NULL ); - _exit( 255 ); - } - else - { - close( input[ 1 ] ); - close( output[ 0 ] ); - - this->reader = fdopen( input[ 0 ], "r" ); - this->writer = fdopen( output[ 1 ], "w" ); - } - } - - return this; -} - -/** Read data from the pipe. -*/ - -static FILE *rwpipe_reader( rwpipe *this ) -{ - if ( this != NULL ) - return this->reader; - else - return NULL; -} - -/** Write data to the pipe. -*/ - -static FILE *rwpipe_writer( rwpipe *this ) -{ - if ( this != NULL ) - return this->writer; - else - return NULL; -} - -/* Read a number from the pipe - assumes PNM style headers. -*/ - -static int rwpipe_read_number( rwpipe *rw ) -{ - int value = 0; - int c = 0; - FILE *in = rwpipe_reader( rw ); - - do - { - c = fgetc( in ); - - while( c != EOF && !isdigit( c ) && c != '#' ) - c = fgetc( in ); - - if ( c == '#' ) - while( c != EOF && c != '\n' ) - c = fgetc( in ); - } - while ( c != EOF && !isdigit( c ) ); - - while( c != EOF && isdigit( c ) ) - { - value = value * 10 + ( c - '0' ); - c = fgetc( in ); - } - - return value; -} - -/** Read a PPM P6 header. -*/ - -static int rwpipe_read_ppm_header( rwpipe *rw, int *width, int *height ) -{ - char line[ 3 ]; - FILE *in = rwpipe_reader( rw ); - int max; - - if (!fgets( line, 3, in )) - return -1; - - if ( !strncmp( line, "P6", 2 ) ) - { - *width = rwpipe_read_number( rw ); - *height = rwpipe_read_number( rw ); - max = rwpipe_read_number( rw ); - return max != 255 || *width <= 0 || *height <= 0; - } - return 1; -} - -/** Close the pipe and process. -*/ - -static void rwpipe_close( rwpipe *this ) -{ - if ( this != NULL ) - { - fclose( this->reader ); - fclose( this->writer ); - waitpid( this->pid, NULL, 0 ); - av_free( this ); - } -} - -/** Context info for this vhook - stores the pipe and image buffers. -*/ - -typedef struct -{ - rwpipe *rw; - int size1; - char *buf1; - int size2; - char *buf2; - - // This vhook first converts frame to RGB ... - struct SwsContext *toRGB_convert_ctx; - // ... then processes it via a PPM command pipe ... - // ... and finally converts back frame from RGB to initial format - struct SwsContext *fromRGB_convert_ctx; -} -ContextInfo; - -/** Initialise the context info for this vhook. -*/ - -int Configure(void **ctxp, int argc, char *argv[]) -{ - if ( argc > 1 ) - { - *ctxp = av_mallocz(sizeof(ContextInfo)); - if ( *ctxp != NULL && argc > 1 ) - { - ContextInfo *info = (ContextInfo *)*ctxp; - info->rw = rwpipe_open( argc - 1, &argv[ 1 ] ); - return 0; - } - } - return 1; -} - -/** Process a frame. -*/ - -void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts) -{ - int err = 0; - ContextInfo *ci = (ContextInfo *) ctx; - AVPicture picture1; - AVPicture picture2; - AVPicture *pict = picture; - int out_width; - int out_height; - int i; - uint8_t *ptr = NULL; - FILE *in = rwpipe_reader( ci->rw ); - FILE *out = rwpipe_writer( ci->rw ); - - /* Check that we have a pipe to talk to. */ - if ( in == NULL || out == NULL ) - err = 1; - - /* Convert to RGB24 if necessary */ - if ( !err && pix_fmt != PIX_FMT_RGB24 ) - { - int size = avpicture_get_size(PIX_FMT_RGB24, width, height); - - if ( size != ci->size1 ) - { - av_free( ci->buf1 ); - ci->buf1 = av_malloc(size); - ci->size1 = size; - err = ci->buf1 == NULL; - } - - if ( !err ) - { - avpicture_fill(&picture1, ci->buf1, PIX_FMT_RGB24, width, height); - - // if we already got a SWS context, let's realloc if is not re-useable - ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, - width, height, pix_fmt, - width, height, PIX_FMT_RGB24, - sws_flags, NULL, NULL, NULL); - if (ci->toRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the toRGB conversion context\n"); - return; - } - -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->toRGB_convert_ctx, - picture->data, picture->linesize, 0, height, - picture1.data, picture1.linesize); - - pict = &picture1; - } - } - - /* Write out the PPM */ - if ( !err ) - { - ptr = pict->data[ 0 ]; - fprintf( out, "P6\n%d %d\n255\n", width, height ); - for ( i = 0; !err && i < height; i ++ ) - { - err = !fwrite( ptr, width * 3, 1, out ); - ptr += pict->linesize[ 0 ]; - } - if ( !err ) - err = fflush( out ); - } - - /* Read the PPM returned. */ - if ( !err && !rwpipe_read_ppm_header( ci->rw, &out_width, &out_height ) ) - { - int size = avpicture_get_size(PIX_FMT_RGB24, out_width, out_height); - - if ( size != ci->size2 ) - { - av_free( ci->buf2 ); - ci->buf2 = av_malloc(size); - ci->size2 = size; - err = ci->buf2 == NULL; - } - - if ( !err ) - { - avpicture_fill(&picture2, ci->buf2, PIX_FMT_RGB24, out_width, out_height); - ptr = picture2.data[ 0 ]; - for ( i = 0; !err && i < out_height; i ++ ) - { - err = !fread( ptr, out_width * 3, 1, in ); - ptr += picture2.linesize[ 0 ]; - } - } - } - - /* Convert the returned PPM back to the input format */ - if ( !err ) - { - /* The out_width/out_height returned from the PPM - * filter won't necessarily be the same as width and height - * but it will be scaled anyway to width/height. - */ - av_log(NULL, AV_LOG_DEBUG, - "PPM vhook: Input dimensions: %d x %d Output dimensions: %d x %d\n", - width, height, out_width, out_height); - ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx, - out_width, out_height, PIX_FMT_RGB24, - width, height, pix_fmt, - sws_flags, NULL, NULL, NULL); - if (ci->fromRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the fromRGB conversion context\n"); - return; - } - -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->fromRGB_convert_ctx, - picture2.data, picture2.linesize, 0, out_height, - picture->data, picture->linesize); - } -} - -/** Clean up the effect. -*/ - -void Release(void *ctx) -{ - ContextInfo *ci; - ci = (ContextInfo *) ctx; - - if (ctx) - { - rwpipe_close( ci->rw ); - av_free( ci->buf1 ); - av_free( ci->buf2 ); - sws_freeContext(ci->toRGB_convert_ctx); - sws_freeContext(ci->fromRGB_convert_ctx); - av_free(ctx); - } -} - diff --git a/vhook/watermark.c b/vhook/watermark.c deleted file mode 100644 index 1d4be28f6c..0000000000 --- a/vhook/watermark.c +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Watermark Hook - * Copyright (c) 2005 Marcus Engene myfirstname(at)mylastname.se - * - * parameters for watermark: - * -m nbr = nbr is 0..1. 0 is the default mode, see below. - * -t nbr = nbr is six digit hex. Threshold. - * -f file = file is the watermark image filename. You must specify this! - * - * MODE 0: - * The watermark picture works like this (assuming color intensities 0..0xff): - * Per color do this: - * If mask color is 0x80, no change to the original frame. - * If mask color is < 0x80 the abs difference is subtracted from the frame. If - * result < 0, result = 0 - * If mask color is > 0x80 the abs difference is added to the frame. If result - * > 0xff, result = 0xff - * - * You can override the 0x80 level with the -t flag. E.g. if threshold is - * 000000 the color value of watermark is added to the destination. - * - * This way a mask that is visible both in light pictures and in dark can be - * made (fex by using a picture generated by Gimp and the bump map tool). - * - * An example watermark file is at - * http://engene.se/ffmpeg_watermark.gif - * - * MODE 1: - * Per color do this: - * If mask color > threshold color then the watermark pixel is used. - * - * Example usage: - * ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif' -an out.mov - * ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif -m 1 -t 222222' -an out.mov - * - * Note that the entire vhook argument is encapsulated in ''. This - * way, arguments to the vhook won't be mixed up with those for ffmpeg. - * - * This file is part of FFmpeg. - * - * FFmpeg 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. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <stdlib.h> -//#include <fcntl.h> -#include <unistd.h> -#include <stdarg.h> - -#include "libavutil/common.h" -#include "libavformat/avformat.h" -#include "libavformat/framehook.h" -#include "libswscale/swscale.h" - -static int sws_flags = SWS_BICUBIC; - -typedef struct { - char filename[2000]; - int x_size; - int y_size; - - /* get_watermark_picture() variables */ - AVFormatContext *pFormatCtx; - const char *p_ext; - int videoStream; - int frameFinished; - AVCodecContext *pCodecCtx; - AVCodec *pCodec; - AVFrame *pFrame; - AVPacket packet; - int numBytes; - uint8_t *buffer; - int i; - AVInputFormat *file_iformat; - AVStream *st; - int is_done; - AVFrame *pFrameRGB; - int thrR; - int thrG; - int thrB; - int mode; - - // This vhook first converts frame to RGB ... - struct SwsContext *toRGB_convert_ctx; - // ... then converts a watermark and applies it to the RGB frame ... - struct SwsContext *watermark_convert_ctx; - // ... and finally converts back frame from RGB to initial format - struct SwsContext *fromRGB_convert_ctx; -} ContextInfo; - -int get_watermark_picture(ContextInfo *ci, int cleanup); - - -/**************************************************************************** - * - ****************************************************************************/ -void Release(void *ctx) -{ - ContextInfo *ci; - ci = (ContextInfo *) ctx; - - if (ci) { - get_watermark_picture(ci, 1); - sws_freeContext(ci->toRGB_convert_ctx); - sws_freeContext(ci->watermark_convert_ctx); - sws_freeContext(ci->fromRGB_convert_ctx); - } - av_free(ctx); -} - - -/**************************************************************************** - * - ****************************************************************************/ -int Configure(void **ctxp, int argc, char *argv[]) -{ - ContextInfo *ci; - int c; - int tmp = 0; - - if (0 == (*ctxp = av_mallocz(sizeof(ContextInfo)))) return -1; - ci = (ContextInfo *) *ctxp; - - optind = 1; - - // Struct is mallocz:ed so no need to reset. - ci->thrR = 0x80; - ci->thrG = 0x80; - ci->thrB = 0x80; - - while ((c = getopt(argc, argv, "f:m:t:")) > 0) { - switch (c) { - case 'f': - strncpy(ci->filename, optarg, 1999); - ci->filename[1999] = 0; - break; - case 'm': - ci->mode = atoi(optarg); - break; - case 't': - if (1 != sscanf(optarg, "%x", &tmp)) { - av_log(NULL, AV_LOG_ERROR, "Watermark: argument to -t must be a 6 digit hex number\n"); - return -1; - } - ci->thrR = (tmp >> 16) & 0xff; - ci->thrG = (tmp >> 8) & 0xff; - ci->thrB = (tmp >> 0) & 0xff; - break; - default: - av_log(NULL, AV_LOG_ERROR, "Watermark: Unrecognized argument '%s'\n", argv[optind]); - return -1; - } - } - - // - if (0 == ci->filename[0]) { - av_log(NULL, AV_LOG_ERROR, "Watermark: There is no filename specified.\n"); - return -1; - } - - av_register_all(); - return get_watermark_picture(ci, 0); -} - - -/**************************************************************************** - * For mode 0 (the original one) - ****************************************************************************/ -static void Process0(void *ctx, - AVPicture *picture, - enum PixelFormat pix_fmt, - int src_width, - int src_height, - int64_t pts) -{ - ContextInfo *ci = (ContextInfo *) ctx; - char *buf = 0; - AVPicture picture1; - AVPicture *pict = picture; - - AVFrame *pFrameRGB; - int xm_size; - int ym_size; - - int x; - int y; - int offs, offsm; - int mpoffs; - uint32_t *p_pixel = 0; - uint32_t pixel_meck; - uint32_t pixel; - uint32_t pixelm; - int tmp; - int thrR = ci->thrR; - int thrG = ci->thrG; - int thrB = ci->thrB; - - if (pix_fmt != PIX_FMT_RGB32) { - int size; - - size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height); - buf = av_malloc(size); - - avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height); - - // if we already got a SWS context, let's realloc if is not re-useable - ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, - src_width, src_height, pix_fmt, - src_width, src_height, PIX_FMT_RGB32, - sws_flags, NULL, NULL, NULL); - if (ci->toRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the toRGB conversion context\n"); - return; - } - -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->toRGB_convert_ctx, - picture->data, picture->linesize, 0, src_height, - picture1.data, picture1.linesize); - - pict = &picture1; - } - - /* Insert filter code here */ /* ok */ - - // Get me next frame - if (0 > get_watermark_picture(ci, 0)) { - return; - } - // These are the three original static variables in the ffmpeg hack. - pFrameRGB = ci->pFrameRGB; - xm_size = ci->x_size; - ym_size = ci->y_size; - - // I'll do the *4 => <<2 crap later. Most compilers understand that anyway. - // According to avcodec.h PIX_FMT_RGB32 is handled in endian specific manner. - for (y=0; y<src_height; y++) { - offs = y * (src_width * 4); - offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs! - for (x=0; x<src_width; x++) { - mpoffs = offsm + (((x * xm_size) / src_width) * 4); - p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]); - pixelm = *p_pixel; - p_pixel = (uint32_t *)&((pict->data[0])[offs]); - pixel = *p_pixel; -// pixelm = *((uint32_t *)&(pFrameRGB->data[mpoffs])); - pixel_meck = pixel & 0xff000000; - - // R - tmp = (int)((pixel >> 16) & 0xff) + (int)((pixelm >> 16) & 0xff) - thrR; - if (tmp > 255) tmp = 255; - if (tmp < 0) tmp = 0; - pixel_meck |= (tmp << 16) & 0xff0000; - // G - tmp = (int)((pixel >> 8) & 0xff) + (int)((pixelm >> 8) & 0xff) - thrG; - if (tmp > 255) tmp = 255; - if (tmp < 0) tmp = 0; - pixel_meck |= (tmp << 8) & 0xff00; - // B - tmp = (int)((pixel >> 0) & 0xff) + (int)((pixelm >> 0) & 0xff) - thrB; - if (tmp > 255) tmp = 255; - if (tmp < 0) tmp = 0; - pixel_meck |= (tmp << 0) & 0xff; - - - // test: - //pixel_meck = pixel & 0xff000000; - //pixel_meck |= (pixelm & 0x00ffffff); - - *p_pixel = pixel_meck; - - offs += 4; - } // foreach X - } // foreach Y - - - - - if (pix_fmt != PIX_FMT_RGB32) { - ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx, - src_width, src_height, PIX_FMT_RGB32, - src_width, src_height, pix_fmt, - sws_flags, NULL, NULL, NULL); - if (ci->fromRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the fromRGB conversion context\n"); - return; - } -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->fromRGB_convert_ctx, - picture1.data, picture1.linesize, 0, src_height, - picture->data, picture->linesize); - } - - av_free(buf); -} - - -/**************************************************************************** - * For mode 1 (the original one) - ****************************************************************************/ -static void Process1(void *ctx, - AVPicture *picture, - enum PixelFormat pix_fmt, - int src_width, - int src_height, - int64_t pts) -{ - ContextInfo *ci = (ContextInfo *) ctx; - char *buf = 0; - AVPicture picture1; - AVPicture *pict = picture; - - AVFrame *pFrameRGB; - int xm_size; - int ym_size; - - int x; - int y; - int offs, offsm; - int mpoffs; - uint32_t *p_pixel = 0; - uint32_t pixel; - uint32_t pixelm; - - if (pix_fmt != PIX_FMT_RGB32) { - int size; - - size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height); - buf = av_malloc(size); - - avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height); - - // if we already got a SWS context, let's realloc if is not re-useable - ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, - src_width, src_height, pix_fmt, - src_width, src_height, PIX_FMT_RGB32, - sws_flags, NULL, NULL, NULL); - if (ci->toRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the toRGB conversion context\n"); - return; - } - -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->toRGB_convert_ctx, - picture->data, picture->linesize, 0, src_height, - picture1.data, picture1.linesize); - - pict = &picture1; - } - - /* Insert filter code here */ /* ok */ - - // Get me next frame - if (0 > get_watermark_picture(ci, 0)) { - return; - } - // These are the three original static variables in the ffmpeg hack. - pFrameRGB = ci->pFrameRGB; - xm_size = ci->x_size; - ym_size = ci->y_size; - - // I'll do the *4 => <<2 crap later. Most compilers understand that anyway. - // According to avcodec.h PIX_FMT_RGB32 is handled in endian specific manner. - for (y=0; y<src_height; y++) { - offs = y * (src_width * 4); - offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs! - for (x=0; x<src_width; x++) { - mpoffs = offsm + (((x * xm_size) / src_width) * 4); - p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]); - pixelm = *p_pixel; /* watermark pixel */ - p_pixel = (uint32_t *)&((pict->data[0])[offs]); - pixel = *p_pixel; - - if (((pixelm >> 16) & 0xff) > ci->thrR || - ((pixelm >> 8) & 0xff) > ci->thrG || - ((pixelm >> 0) & 0xff) > ci->thrB) - { - *p_pixel = pixelm; - } else { - *p_pixel = pixel; - } - offs += 4; - } // foreach X - } // foreach Y - - if (pix_fmt != PIX_FMT_RGB32) { - ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx, - src_width, src_height, PIX_FMT_RGB32, - src_width, src_height, pix_fmt, - sws_flags, NULL, NULL, NULL); - if (ci->fromRGB_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the fromRGB conversion context\n"); - return; - } -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->fromRGB_convert_ctx, - picture1.data, picture1.linesize, 0, src_height, - picture->data, picture->linesize); - } - - av_free(buf); -} - - -/**************************************************************************** - * This is the function ffmpeg.c callbacks. - ****************************************************************************/ -void Process(void *ctx, - AVPicture *picture, - enum PixelFormat pix_fmt, - int src_width, - int src_height, - int64_t pts) -{ - ContextInfo *ci = (ContextInfo *) ctx; - if (1 == ci->mode) { - Process1(ctx, picture, pix_fmt, src_width, src_height, pts); - } else { - Process0(ctx, picture, pix_fmt, src_width, src_height, pts); - } -} - - -/**************************************************************************** - * When cleanup == 0, we try to get the next frame. If no next frame, nothing - * is done. - * - * This code follows the example on - * http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html - * - * 0 = ok, -1 = error - ****************************************************************************/ -int get_watermark_picture(ContextInfo *ci, int cleanup) -{ - if (1 == ci->is_done && 0 == cleanup) return 0; - - // Yes, *pFrameRGB arguments must be null the first time otherwise it's not good.. - // This block is only executed the first time we enter this function. - if (0 == ci->pFrameRGB && - 0 == cleanup) - { - - /* - * The last three parameters specify the file format, buffer size and format - * parameters; by simply specifying NULL or 0 we ask libavformat to auto-detect - * the format and use a default buffer size. (Didn't work!) - */ - if (av_open_input_file(&ci->pFormatCtx, ci->filename, NULL, 0, NULL) != 0) { - - // Martin says this should not be necessary but it failed for me sending in - // NULL instead of file_iformat to av_open_input_file() - ci->i = strlen(ci->filename); - if (0 == ci->i) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() No filename to watermark vhook\n"); - return -1; - } - while (ci->i > 0) { - if (ci->filename[ci->i] == '.') { - ci->i++; - break; - } - ci->i--; - } - ci->p_ext = &(ci->filename[ci->i]); - ci->file_iformat = av_find_input_format (ci->p_ext); - if (0 == ci->file_iformat) { - av_log(NULL, AV_LOG_INFO, "get_watermark_picture() attempt to use image2 for [%s]\n", ci->p_ext); - ci->file_iformat = av_find_input_format ("image2"); - } - if (0 == ci->file_iformat) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Really failed to find iformat [%s]\n", ci->p_ext); - return -1; - } - // now continues the Martin template. - - if (av_open_input_file(&ci->pFormatCtx, ci->filename, ci->file_iformat, 0, NULL)!=0) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open input file [%s]\n", ci->filename); - return -1; - } - } - - /* - * This fills the streams field of the AVFormatContext with valid information. - */ - if(av_find_stream_info(ci->pFormatCtx)<0) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find stream info\n"); - return -1; - } - - /* - * As mentioned in the introduction, we'll handle only video streams, not audio - * streams. To make things nice and easy, we simply use the first video stream we - * find. - */ - ci->videoStream=-1; - for(ci->i = 0; ci->i < ci->pFormatCtx->nb_streams; ci->i++) - if(ci->pFormatCtx->streams[ci->i]->codec->codec_type==CODEC_TYPE_VIDEO) - { - ci->videoStream = ci->i; - break; - } - if(ci->videoStream == -1) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any video stream\n"); - return -1; - } - - ci->st = ci->pFormatCtx->streams[ci->videoStream]; - ci->x_size = ci->st->codec->width; - ci->y_size = ci->st->codec->height; - - // Get a pointer to the codec context for the video stream - ci->pCodecCtx = ci->pFormatCtx->streams[ci->videoStream]->codec; - - - /* - * OK, so now we've got a pointer to the so-called codec context for our video - * stream, but we still have to find the actual codec and open it. - */ - // Find the decoder for the video stream - ci->pCodec = avcodec_find_decoder(ci->pCodecCtx->codec_id); - if(ci->pCodec == NULL) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any codec\n"); - return -1; - } - - - // Open codec - if(avcodec_open(ci->pCodecCtx, ci->pCodec)<0) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open codec\n"); - return -1; - } - - // Hack to correct wrong frame rates that seem to be generated by some - // codecs - if (ci->pCodecCtx->time_base.den>1000 && ci->pCodecCtx->time_base.num==1) - ci->pCodecCtx->time_base.num=1000; - - /* - * Allocate a video frame to store the decoded images in. - */ - ci->pFrame = avcodec_alloc_frame(); - - - /* - * The RGB image pFrameRGB (of type AVFrame *) is allocated like this: - */ - // Allocate an AVFrame structure - ci->pFrameRGB=avcodec_alloc_frame(); - if(ci->pFrameRGB==NULL) { - av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to alloc pFrameRGB\n"); - return -1; - } - - // Determine required buffer size and allocate buffer - ci->numBytes = avpicture_get_size(PIX_FMT_RGB32, ci->pCodecCtx->width, - ci->pCodecCtx->height); - ci->buffer = av_malloc(ci->numBytes); - - // Assign appropriate parts of buffer to image planes in pFrameRGB - avpicture_fill((AVPicture *)ci->pFrameRGB, ci->buffer, PIX_FMT_RGB32, - ci->pCodecCtx->width, ci->pCodecCtx->height); - } - // TODO loop, pingpong etc? - if (0 == cleanup) - { -// av_log(NULL, AV_LOG_DEBUG, "get_watermark_picture() Get a frame\n"); - while(av_read_frame(ci->pFormatCtx, &ci->packet)>=0) - { - // Is this a packet from the video stream? - if(ci->packet.stream_index == ci->videoStream) - { - // Decode video frame - avcodec_decode_video(ci->pCodecCtx, ci->pFrame, &ci->frameFinished, - ci->packet.data, ci->packet.size); - - // Did we get a video frame? - if(ci->frameFinished) - { - // Convert the image from its native format to RGB32 - ci->watermark_convert_ctx = - sws_getCachedContext(ci->watermark_convert_ctx, - ci->pCodecCtx->width, ci->pCodecCtx->height, ci->pCodecCtx->pix_fmt, - ci->pCodecCtx->width, ci->pCodecCtx->height, PIX_FMT_RGB32, - sws_flags, NULL, NULL, NULL); - if (ci->watermark_convert_ctx == NULL) { - av_log(NULL, AV_LOG_ERROR, - "Cannot initialize the watermark conversion context\n"); - return -1; - } -// img_convert parameters are 2 first destination, then 4 source -// sws_scale parameters are context, 4 first source, then 2 destination - sws_scale(ci->watermark_convert_ctx, - ci->pFrame->data, ci->pFrame->linesize, 0, ci->pCodecCtx->height, - ci->pFrameRGB->data, ci->pFrameRGB->linesize); - - // Process the video frame (save to disk etc.) - //fprintf(stderr,"banan() New frame!\n"); - //DoSomethingWithTheImage(ci->pFrameRGB); - return 0; - } - } - - // Free the packet that was allocated by av_read_frame - av_free_packet(&ci->packet); - } - ci->is_done = 1; - return 0; - } // if 0 != cleanup - - if (0 != cleanup) - { - // Free the RGB image - av_freep(&ci->buffer); - av_freep(&ci->pFrameRGB); - - // Close the codec - if (0 != ci->pCodecCtx) { - avcodec_close(ci->pCodecCtx); - ci->pCodecCtx = 0; - } - - // Close the video file - if (0 != ci->pFormatCtx) { - av_close_input_file(ci->pFormatCtx); - ci->pFormatCtx = 0; - } - - ci->is_done = 0; - } - return 0; -} - - -void parse_arg_file(const char *filename) -{ -} |