Revision fdf11906

View differences:

MAINTAINERS
18 18
ffmpeg:
19 19
  ffmpeg.c                              Michael Niedermayer
20 20

  
21
  Video Hooks:
22
    vhook
23
    vhook/watermark.c                   Marcus Engene
24
    vhook/ppm.c
25
    vhook/drawtext.c
26
    vhook/fish.c
27
    vhook/null.c
28
    vhook/imlib2.c
29

  
30 21
ffplay:
31 22
  ffplay.c                              Michael Niedermayer
32 23

  
Makefile
32 32
FF_EXTRALIBS := $(FFEXTRALIBS)
33 33
FF_DEP_LIBS  := $(DEP_LIBS)
34 34

  
35
ALL_TARGETS-$(CONFIG_VHOOK) += videohook
36 35
ALL_TARGETS-$(BUILD_DOC)    += documentation
37 36

  
38
INSTALL_TARGETS-$(CONFIG_VHOOK) += install-vhook
39 37
ifneq ($(PROGS),)
40 38
INSTALL_TARGETS-yes             += install-progs install-data
41 39
INSTALL_TARGETS-$(BUILD_DOC)    += install-man
......
81 79

  
82 80
alltools: $(addsuffix $(EXESUF),$(addprefix tools/, cws2fws pktdumper qt-faststart trasher))
83 81

  
84
VHOOKCFLAGS += $(filter-out -mdynamic-no-pic,$(CFLAGS))
85

  
86
BASEHOOKS = fish null watermark
87
ALLHOOKS = $(BASEHOOKS) drawtext imlib2 ppm
88
ALLHOOKS_SRCS = $(addprefix vhook/, $(addsuffix .c, $(ALLHOOKS)))
89

  
90
HOOKS-$(HAVE_FORK)      += ppm
91
HOOKS-$(HAVE_IMLIB2)    += imlib2
92
HOOKS-$(HAVE_FREETYPE2) += drawtext
93

  
94
HOOKS = $(addprefix vhook/, $(addsuffix $(SLIBSUF), $(BASEHOOKS) $(HOOKS-yes)))
95

  
96
VHOOKCFLAGS-$(HAVE_IMLIB2) += `imlib2-config --cflags`
97
LIBS_imlib2$(SLIBSUF)       = `imlib2-config --libs`
98

  
99
VHOOKCFLAGS-$(HAVE_FREETYPE2) += `freetype-config --cflags`
100
LIBS_drawtext$(SLIBSUF)        = `freetype-config --libs`
101

  
102
VHOOKCFLAGS += $(VHOOKCFLAGS-yes)
103

  
104
vhook/%.o vhook/%.d: CFLAGS:=$(VHOOKCFLAGS)
105

  
106
# vhooks compile fine without libav*, but need them nonetheless.
107
videohook: $(FF_DEP_LIBS) $(HOOKS)
108

  
109
$(eval VHOOKSHFLAGS=$(VHOOKSHFLAGS))
110
vhook/%$(SLIBSUF): vhook/%.o
111
	$(CC) $(LDFLAGS) -o $@ $(VHOOKSHFLAGS) $< $(VHOOKLIBS) $(LIBS_$(@F))
112

  
113
VHOOK_DEPS = $(HOOKS:$(SLIBSUF)=.d)
114
depend dep: $(VHOOK_DEPS)
115

  
116 82
documentation: $(addprefix doc/, ffmpeg-doc.html faq.html ffserver-doc.html \
117
                                 ffplay-doc.html general.html hooks.html \
118
                                 $(ALLMANPAGES))
83
                                 ffplay-doc.html general.html $(ALLMANPAGES))
119 84

  
120 85
doc/%.html: doc/%.texi
121 86
	texi2html -monolithic -number $<
......
141 106
	install -d "$(MANDIR)/man1"
142 107
	install -m 644 $(MANPAGES) "$(MANDIR)/man1"
143 108

  
144
install-vhook: videohook
145
	install -d "$(SHLIBDIR)/vhook"
146
	install -m 755 $(HOOKS) "$(SHLIBDIR)/vhook"
147

  
148
uninstall: uninstall-progs uninstall-data uninstall-man uninstall-vhook
109
uninstall: uninstall-progs uninstall-data uninstall-man
149 110

  
150 111
uninstall-progs:
151 112
	rm -f $(addprefix "$(BINDIR)/", $(ALLPROGS))
......
156 117
uninstall-man:
157 118
	rm -f $(addprefix "$(MANDIR)/man1/",$(ALLMANPAGES))
158 119

  
159
uninstall-vhook:
160
	rm -f $(addprefix "$(SHLIBDIR)/",$(ALLHOOKS_SRCS:.c=$(SLIBSUF)))
161
	-rmdir "$(SHLIBDIR)/vhook/"
162

  
163 120
testclean:
164 121
	rm -rf tests/vsynth1 tests/vsynth2 tests/data tests/asynth1.sw tests/*~
165 122

  
......
168 125
	rm -f doc/*.html doc/*.pod doc/*.1
169 126
	rm -f $(addprefix tests/,$(addsuffix $(EXESUF),audiogen videogen rotozoom seek_test tiny_psnr))
170 127
	rm -f $(addprefix tools/,$(addsuffix $(EXESUF),cws2fws pktdumper qt-faststart trasher))
171
	rm -f vhook/*.o vhook/*~ vhook/*.so vhook/*.dylib vhook/*.dll
172 128

  
173 129
distclean::
174
	rm -f version.h config.* vhook/*.d
130
	rm -f version.h config.*
175 131

  
176 132
# regression tests
177 133

  
......
355 311
	$(CC) $(FF_LDFLAGS) $(CFLAGS) -o $@ $< $(FF_EXTRALIBS)
356 312

  
357 313

  
358
.PHONY: lib videohook documentation *test regtest-* swscale-error zlib-error alltools check
359

  
360
-include $(VHOOK_DEPS)
314
.PHONY: lib documentation *test regtest-* swscale-error zlib-error alltools check
configure
82 82
  echo "  --disable-ffserver       disable ffserver build"
83 83
  echo "  --enable-postproc        enable GPLed postprocessing support [no]"
84 84
  echo "  --enable-swscale         enable GPLed software scaler support [no]"
85
  echo "  --enable-avfilter        video filter support (replaces vhook) [no]"
85
  echo "  --enable-avfilter        video filter support [no]"
86 86
  echo "  --enable-avfilter-lavf   video filters dependent on avformat [no]"
87
  echo "  --disable-vhook          disable video hooking support"
88 87
  echo "  --enable-beosthreads     use BeOS threads [no]"
89 88
  echo "  --enable-os2threads      use OS/2 threads [no]"
90 89
  echo "  --enable-pthreads        use pthreads [no]"
......
799 798
    static
800 799
    swscale
801 800
    vdpau
802
    vhook
803 801
    x11grab
804 802
    zlib
805 803
"
......
873 871
    fast_cmov
874 872
    fast_unaligned
875 873
    fork
876
    freetype2
877 874
    gethrtime
878 875
    GetProcessTimes
879 876
    getrusage
880
    imlib2
881 877
    inet_aton
882 878
    inline_asm
883 879
    libdc1394_1
......
1133 1129
ffplay_deps="sdl"
1134 1130
ffserver_deps="ffm_muxer rtp_protocol rtsp_demuxer"
1135 1131
ffserver_extralibs='$ldl'
1136
vhook_extralibs='$ldl'
1137 1132

  
1138 1133

  
1139 1134
# default parameters
......
1180 1175
enable protocols
1181 1176
enable static
1182 1177
enable stripping
1183
vhook="default"
1184 1178

  
1185 1179
# build settings
1186 1180
add_cflags -D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112
1187 1181
SHFLAGS='-shared -Wl,-soname,$$(@F)'
1188
VHOOKSHFLAGS='$(SHFLAGS)'
1189 1182
FFSERVERLDFLAGS=-Wl,-E
1190 1183
LIBPREF="lib"
1191 1184
LIBSUF=".a"
......
1560 1553
    darwin)
1561 1554
        disable need_memalign
1562 1555
        SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR) -Wl,-read_only_relocs,suppress'
1563
        VHOOKSHFLAGS='-dynamiclib -Wl,-single_module -flat_namespace -undefined suppress -Wl,-install_name,$(SHLIBDIR)/vhook/$$(@F)'
1564 1556
        strip="strip -x"
1565 1557
        FFLDFLAGS="-Wl,-dynamic,-search_paths_first"
1566 1558
        SLIBSUF=".dylib"
......
1578 1570
            LIBTARGET=x64
1579 1571
        fi
1580 1572
        shlibdir_default="$bindir_default"
1581
        VHOOKSHFLAGS='-shared -L$(BUILD_ROOT)/libavformat -L$(BUILD_ROOT)/libavcodec -L$(BUILD_ROOT)/libavutil'
1582
        VHOOKLIBS='-lavformat$(BUILDSUF) -lavcodec$(BUILDSUF) -lavutil$(BUILDSUF) $(EXTRALIBS)'
1583
        if enabled swscale; then
1584
            VHOOKSHFLAGS="$VHOOKSHFLAGS -L\$(BUILD_ROOT)/libswscale"
1585
            VHOOKLIBS="$VHOOKLIBS -lswscale\$(BUILDSUF)"
1586
        fi
1587 1573
        disable ffserver
1588 1574
        SLIBPREF=""
1589 1575
        SLIBSUF=".dll"
......
1607 1593
    cygwin*)
1608 1594
        target_os=cygwin
1609 1595
        shlibdir_default="$bindir_default"
1610
        VHOOKSHFLAGS='-shared -L$(BUILD_ROOT)/libavformat -L$(BUILD_ROOT)/libavcodec -L$(BUILD_ROOT)/libavutil'
1611
        VHOOKLIBS='-lavformat$(BUILDSUF) -lavcodec$(BUILDSUF) -lavutil$(BUILDSUF) $(EXTRALIBS)'
1612
        if enabled swscale; then
1613
            VHOOKSHFLAGS="$VHOOKSHFLAGS -L\$(BUILD_ROOT)/libswscale"
1614
            VHOOKLIBS="$VHOOKLIBS -lswscale\$(BUILDSUF)"
1615
        fi
1616 1596
        SLIBPREF="cyg"
1617 1597
        SLIBSUF=".dll"
1618 1598
        SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
......
1622 1602
        enable dos_paths
1623 1603
        ;;
1624 1604
    *-dos|freedos|opendos)
1625
        disable ffplay ffserver vhook
1605
        disable ffplay ffserver
1626 1606
        disable $INDEV_LIST $OUTDEV_LIST
1627 1607
        network_extralibs="-lsocket"
1628 1608
        objformat="coff"
......
1656 1636
          emximp -o $(SUBDIR)$(LIBPREF)$(NAME)_dll.lib $(SUBDIR)$(NAME).def;'
1657 1637
        SLIB_INSTALL_EXTRA_CMD='install -m 644 $(SUBDIR)$(LIBPREF)$(NAME)_dll.a $(SUBDIR)$(LIBPREF)$(NAME)_dll.lib "$(LIBDIR)"'
1658 1638
        SLIB_UNINSTALL_EXTRA_CMD='rm -f "$(LIBDIR)"/$(LIBPREF)$(NAME)_dll.a "$(LIBDIR)"/$(LIBPREF)$(NAME)_dll.lib'
1659
        disable vhook
1660 1639
        enable dos_paths
1661 1640
        ;;
1662
    interix)
1663
        disable vhook
1664
        ;;
1665 1641

  
1666 1642
    *)
1667 1643
        die "Unknown OS '$target_os'."
......
2040 2016
EOF
2041 2017
done
2042 2018

  
2043
test "$vhook" = "default" && vhook="$dlopen"
2044

  
2045
if test "$target_os" = cygwin -o "$target_os" = mingw32 && enabled_all static vhook ; then
2046
    disable vhook
2047
    echo
2048
    echo "At the moment vhooks don't work on Cygwin or MinGW static builds."
2049
    echo "Patches welcome."
2050
    echo
2051
fi
2052

  
2053
if enabled vhook; then
2054
    check_ldflags -rdynamic
2055
    check_ldflags -export-dynamic
2056
fi
2057

  
2058
check_foo_config imlib2 imlib2 Imlib2.h imlib_load_font
2059
check_foo_config freetype2 freetype ft2build.h FT_Init_FreeType
2060

  
2061 2019
##########################################
2062 2020
# SDL check
2063 2021

  
......
2225 2183
    add_ldflags -p
2226 2184
fi
2227 2185

  
2228
VHOOKCFLAGS="-fPIC"
2229

  
2230 2186
# Find out if the .align argument is a power of two or not.
2231 2187
check_asm asmalign_pot '".align 3"'
2232 2188

  
......
2312 2268
echo "software scaler enabled   ${swscale-no}"
2313 2269
echo "new filter support        ${avfilter-no}"
2314 2270
echo "filters using lavformat   ${avfilter_lavf-no}"
2315
echo "video hooking             ${vhook-no}"
2316
if enabled vhook; then
2317
    echo "Imlib2 support            ${imlib2-no}"
2318
    echo "FreeType support          ${freetype2-no}"
2319
fi
2320 2271
echo "network support           ${network-no}"
2321 2272
if enabled network; then
2322 2273
    echo "IPv6 support              ${ipv6-no}"
......
2395 2346
    echo "STRIP=echo ignoring strip" >> config.mak
2396 2347

  
2397 2348
echo "OPTFLAGS=$CFLAGS" >> config.mak
2398
echo "VHOOKCFLAGS=$VHOOKCFLAGS" >> config.mak
2399 2349
echo "LDFLAGS=$LDFLAGS" >> config.mak
2400 2350
echo "FFSERVERLDFLAGS=$FFSERVERLDFLAGS" >> config.mak
2401 2351
echo "SHFLAGS=$SHFLAGS" >> config.mak
2402 2352
echo "YASMFLAGS=$YASMFLAGS" >> config.mak
2403
echo "VHOOKSHFLAGS=$VHOOKSHFLAGS" >> config.mak
2404
echo "VHOOKLIBS=$VHOOKLIBS" >> config.mak
2405 2353
echo "LIBOBJFLAGS=$LIBOBJFLAGS" >> config.mak
2406 2354
echo "BUILD_STATIC=$static" >> config.mak
2407 2355
echo "BUILDSUF=$build_suffix" >> config.mak
......
2529 2477
        libswscale        \
2530 2478
        tests             \
2531 2479
        tools             \
2532
        vhook             \
2533 2480
        "
2534 2481
    FILES="\
2535 2482
        Makefile             \
doc/ffmpeg-doc.texi
660 660
Dump video coding statistics to @file{vstats_HHMMSS.log}.
661 661
@item -vstats_file @var{file}
662 662
Dump video coding statistics to @var{file}.
663
@item -vhook @var{module}
664
Insert video processing @var{module}. @var{module} contains the module
665
name and its parameters separated by spaces.
666 663
@item -top @var{n}
667 664
top=1/bottom=0/auto=-1 field first
668 665
@item -dc @var{precision}
doc/general.texi
691 691

  
692 692
@itemize
693 693

  
694
@item In order to compile vhooks, you must have a POSIX-compliant libdl in
695
your MinGW system. Get dlfcn-win32 from
696
@url{http://code.google.com/p/dlfcn-win32}.
697

  
698 694
@item In order to compile FFplay, you must have the MinGW development library
699 695
of SDL. Get it from @url{http://www.libsdl.org}.
700 696
Edit the @file{bin/sdl-config} script so that it points to the correct prefix
doc/hooks.texi
1
\input texinfo @c -*- texinfo -*-
2

  
3
@settitle Video Hook Documentation
4
@titlepage
5
@sp 7
6
@center @titlefont{Video Hook Documentation}
7
@sp 3
8
@end titlepage
9

  
10

  
11
@chapter Introduction
12

  
13
@var{Please be aware that vhook is deprecated, and hence its development is
14
frozen (bug fixes are still accepted).
15
The substitute will be 'libavfilter', the result of our 'Video Filter API'
16
Google Summer of Code project. You may monitor its progress by subscribing to
17
the ffmpeg-soc mailing list at
18
@url{http://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc}.}
19

  
20
The video hook functionality is designed (mostly) for live video. It allows
21
the video to be modified or examined between the decoder and the encoder.
22

  
23
Any number of hook modules can be placed inline, and they are run in the
24
order that they were specified on the ffmpeg command line.
25

  
26
The video hook modules are provided for use as a base for your own modules,
27
and are described below.
28

  
29
Modules are loaded using the -vhook option to ffmpeg. The value of this parameter
30
is a space separated list of arguments. The first is the module name, and the rest
31
are passed as arguments to the Configure function of the module.
32

  
33
The modules are dynamic libraries: They have different suffixes (.so, .dll, .dylib)
34
depending on your platform. And your platform dictates if they need to be
35
somewhere in your PATH, or in your LD_LIBRARY_PATH. Otherwise you will need to
36
specify the full path of the vhook file that you are using.
37

  
38
@section null.c
39

  
40
This does nothing. Actually it converts the input image to RGB24 and then converts
41
it back again. This is meant as a sample that you can use to test your setup.
42

  
43
@section fish.c
44

  
45
This implements a 'fish detector'. Essentially it converts the image into HSV
46
space and tests whether more than a certain percentage of the pixels fall into
47
a specific HSV cuboid. If so, then the image is saved into a file for processing
48
by other bits of code.
49

  
50
Why use HSV? It turns out that HSV cuboids represent a more compact range of
51
colors than would an RGB cuboid.
52

  
53
@section imlib2.c
54

  
55
This module implements a text overlay for a video image. Currently it
56
supports a fixed overlay or reading the text from a file. The string
57
is passed through strftime() so that it is easy to imprint the date and
58
time onto the image.
59

  
60
This module depends on the external library imlib2, available on
61
Sourceforge, among other places, if it is not already installed on
62
your system.
63

  
64
You may also overlay an image (even semi-transparent) like TV stations do.
65
You may move either the text or the image around your video to create
66
scrolling credits, for example.
67

  
68
The font file used is looked for in a FONTPATH environment variable, and
69
prepended to the point size as a command line option and can be specified
70
with the full path to the font file, as in:
71
@example
72
-F /usr/X11R6/lib/X11/fonts/TTF/VeraBd.ttf/20
73
@end example
74
where 20 is the point size.
75

  
76
You can specify the filename to read RGB color names from. If it is not
77
specified, these defaults are used: @file{/usr/share/X11/rgb.txt} and
78
@file{/usr/lib/X11/rgb.txt}
79

  
80
Options:
81
@multitable @columnfractions .2 .8
82
@item @option{-C <rgb.txt>}   @tab The filename to read RGB color names from
83
@item @option{-c <color>}     @tab The color of the text
84
@item @option{-F <fontname>}  @tab The font face and size
85
@item @option{-t <text>}      @tab The text
86
@item @option{-f <filename>}  @tab The filename to read text from
87
@item @option{-x <expression>}@tab x coordinate of text or image
88
@item @option{-y <expression>}@tab y coordinate of text or image
89
@item @option{-i <filename>}  @tab The filename to read a image from
90
@item @option{-R <expression>}@tab Value for R color
91
@item @option{-G <expression>}@tab Value for G color
92
@item @option{-B <expression>}@tab Value for B color
93
@item @option{-A <expression>}@tab Value for Alpha channel
94
@end multitable
95

  
96
Expressions are functions of these variables:
97
@multitable @columnfractions .2 .8
98
@item @var{N} @tab frame number (starting at zero)
99
@item @var{H} @tab frame height
100
@item @var{W} @tab frame width
101
@item @var{h} @tab image height
102
@item @var{w} @tab image width
103
@item @var{X} @tab previous x coordinate of text or image
104
@item @var{Y} @tab previous y coordinate of text or image
105
@end multitable
106

  
107
You may also use the constants @var{PI}, @var{E}, and the math functions available at the
108
FFmpeg formula evaluator at (@url{ffmpeg-doc.html#SEC13}), except @var{bits2qp(bits)}
109
and @var{qp2bits(qp)}.
110

  
111
Usage examples:
112

  
113
@example
114
   # Remember to set the path to your fonts
115
   FONTPATH="/cygdrive/c/WINDOWS/Fonts/"
116
   FONTPATH="$FONTPATH:/usr/share/imlib2/data/fonts/"
117
   FONTPATH="$FONTPATH:/usr/X11R6/lib/X11/fonts/TTF/"
118
   export FONTPATH
119

  
120
   # Bulb dancing in a Lissajous pattern
121
   ffmpeg -i input.avi -vhook \
122
     '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' \
123
     -acodec copy -sameq output.avi
124

  
125
   # Text scrolling
126
   ffmpeg -i input.avi -vhook \
127
     'vhook/imlib2.dll -c red -F Vera.ttf/20 -x 150+0.5*N -y 70+0.25*N -t Hello' \
128
     -acodec copy -sameq output.avi
129

  
130
   # Date and time stamp, security-camera style:
131
   ffmpeg -r 29.97 -s 320x256 -f video4linux -i /dev/video0 \
132
     -vhook 'vhook/imlib2.so -x 0 -y 0 -i black-260x20.png' \
133
     -vhook 'vhook/imlib2.so -c white -F VeraBd.ttf/12 -x 0 -y 0 -t %A-%D-%T' \
134
     output.avi
135

  
136
     In this example the video is captured from the first video capture card as a
137
     320x256 AVI, and a black 260 by 20 pixel PNG image is placed in the upper
138
     left corner, with the day, date and time overlaid on it in Vera Bold 12
139
     point font. A simple black PNG file 260 pixels wide and 20 pixels tall
140
     was created in the GIMP for this purpose.
141

  
142
   # Scrolling credits from a text file
143
   ffmpeg -i input.avi -vhook \
144
     'vhook/imlib2.so -c white -F VeraBd.ttf/16 -x 100 -y -1.0*N -f credits.txt' \
145
     -sameq output.avi
146

  
147
     In this example, the text is stored in a file, and is positioned 100
148
     pixels from the left hand edge of the video. The text is scrolled from the
149
     bottom up. Making the y factor positive will scroll from the top down.
150
     Increasing the magnitude of the y factor makes the text scroll faster,
151
     decreasing it makes it scroll slower. Hint: Blank lines containing only
152
     a newline are treated as end-of-file. To create blank lines, use lines
153
     that consist of space characters only.
154

  
155
   # Scrolling credits with custom color from a text file
156
   ffmpeg -i input.avi -vhook \
157
     'vhook/imlib2.so -C rgb.txt -c CustomColor1 -F VeraBd.ttf/16 -x 100 -y -1.0*N -f credits.txt' \
158
     -sameq output.avi
159

  
160
     This example does the same as the one above, but specifies an rgb.txt file
161
     to be used, which has a custom-made color in it.
162

  
163
   # Variable colors
164
   ffmpeg -i input.avi -vhook \
165
     '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))' \
166
     -sameq output.avi
167

  
168
     In this example, the color for the text goes up and down from black to
169
     white.
170

  
171
   # Text fade-out
172
   ffmpeg -i input.avi -vhook \
173
     'vhook/imlib2.so -t Hello -A max(0,255-exp(N/47))' \
174
     -sameq output.avi
175

  
176
     In this example, the text fades out in about 10 seconds for a 25 fps input
177
     video file.
178

  
179
   # scrolling credits from a graphics file
180
   ffmpeg -sameq -i input.avi \
181
     -vhook 'vhook/imlib2.so -x 0 -y -1.0*N -i credits.png' output.avi
182

  
183
     In this example, a transparent PNG file the same width as the video
184
     (e.g. 320 pixels), but very long, (e.g. 3000 pixels), was created, and
185
     text, graphics, brushstrokes, etc, were added to the image. The image
186
     is then scrolled up, from the bottom of the frame.
187

  
188
@end example
189

  
190
@section ppm.c
191

  
192
It's basically a launch point for a PPM pipe, so you can use any
193
executable (or script) which consumes a PPM on stdin and produces a PPM
194
on stdout (and flushes each frame). The Netpbm utilities are a series of
195
such programs.
196

  
197
A list of them is here:
198

  
199
@url{http://netpbm.sourceforge.net/doc/directory.html}
200

  
201
Usage example:
202

  
203
@example
204
ffmpeg -i input -vhook "/path/to/ppm.so some-ppm-filter args" output
205
@end example
206

  
207
@section drawtext.c
208

  
209
This module implements a text overlay for a video image. Currently it
210
supports a fixed overlay or reading the text from a file. The string
211
is passed through strftime() so that it is easy to imprint the date and
212
time onto the image.
213

  
214
Features:
215
@itemize @minus
216
@item TrueType, Type1 and others via the FreeType2 library
217
@item Font kerning (better output)
218
@item Line Wrap (put the text that doesn't fit one line on the next line)
219
@item Background box (currently in development)
220
@item Outline
221
@end itemize
222

  
223
Options:
224
@multitable @columnfractions .2 .8
225
@item @option{-c <color>}          @tab Foreground color of the text ('internet' way) <#RRGGBB> [default #FFFFFF]
226
@item @option{-C <color>}          @tab Background color of the text ('internet' way) <#RRGGBB> [default #000000]
227
@item @option{-f <font-filename>}  @tab font file to use
228
@item @option{-t <text>}           @tab text to display
229
@item @option{-T <filename>}       @tab file to read text from
230
@item @option{-x <pos>}            @tab x coordinate of the start of the text
231
@item @option{-y <pos>}            @tab y coordinate of the start of the text
232
@end multitable
233

  
234
Text fonts are being looked for in a FONTPATH environment variable.
235
If the FONTPATH environment variable is not available, or is not checked by
236
your target (i.e. Cygwin), then specify the full path to the font file as in:
237
@example
238
-f /usr/X11R6/lib/X11/fonts/TTF/VeraBd.ttf
239
@end example
240

  
241
Usage Example:
242
@example
243
   # Remember to set the path to your fonts
244
   FONTPATH="/cygdrive/c/WINDOWS/Fonts/"
245
   FONTPATH="$FONTPATH:/usr/share/imlib2/data/fonts/"
246
   FONTPATH="$FONTPATH:/usr/X11R6/lib/X11/fonts/TTF/"
247
   export FONTPATH
248

  
249
   # Time and date display
250
   ffmpeg -f video4linux2 -i /dev/video0 \
251
   -vhook 'vhook/drawtext.so -f VeraBd.ttf -t %A-%D-%T' movie.mpg
252

  
253
     This example grabs video from the first capture card and outputs it to an
254
     MPEG video, and places "Weekday-dd/mm/yy-hh:mm:ss" at the top left of the
255
     frame, updated every second, using the Vera Bold TrueType Font, which
256
     should exist in: /usr/X11R6/lib/X11/fonts/TTF/
257
@end example
258

  
259
Check the man page for strftime() for all the various ways you can format
260
the date and time.
261

  
262
@section watermark.c
263

  
264
Command Line options:
265
@multitable @columnfractions .2 .8
266
@item @option{-m [0|1]}            @tab Mode (default: 0, see below)
267
@item @option{-t 000000 - FFFFFF}  @tab Threshold, six digit hex number
268
@item @option{-f <filename>}       @tab Watermark image filename, must be specified!
269
@end multitable
270

  
271
MODE 0:
272
 The watermark picture works like this (assuming color intensities 0..0xFF):
273
 Per color do this:
274
 If mask color is 0x80, no change to the original frame.
275
 If mask color is < 0x80 the absolute difference is subtracted from the
276
 frame. If result < 0, result = 0.
277
 If mask color is > 0x80 the absolute difference is added to the
278
 frame. If result > 0xFF, result = 0xFF.
279

  
280
 You can override the 0x80 level with the -t flag. E.g. if threshold is
281
 000000 the color value of watermark is added to the destination.
282

  
283
 This way a mask that is visible both in light and dark pictures can be made
284
 (e.g. by using a picture generated by the Gimp and the bump map tool).
285

  
286
 An example watermark file is at:
287
 @url{http://engene.se/ffmpeg_watermark.gif}
288

  
289
MODE 1:
290
 Per color do this:
291
 If mask color > threshold color then the watermark pixel is used.
292

  
293
Example usage:
294
@example
295
   ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif' -an out.mov
296
   ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif -m 1 -t 222222' -an out.mov
297
@end example
298

  
299
@bye
ffmpeg.c
34 34
#include "libavformat/avformat.h"
35 35
#include "libavdevice/avdevice.h"
36 36
#include "libswscale/swscale.h"
37
#include "libavformat/framehook.h"
38 37
#include "libavcodec/opt.h"
39 38
#include "libavcodec/audioconvert.h"
40 39
#include "libavutil/fifo.h"
......
203 202

  
204 203
static int exit_on_error = 0;
205 204
static int using_stdin = 0;
206
static int using_vhook = 0;
207 205
static int verbose = 1;
208 206
static int thread_count= 1;
209 207
static int q_pressed = 0;
......
736 734
    dec = ist->st->codec;
737 735

  
738 736
    /* deinterlace : must be done before any resize */
739
    if (do_deinterlace || using_vhook) {
737
    if (do_deinterlace) {
740 738
        int size;
741 739

  
742 740
        /* create temporary picture */
......
764 762
        picture2 = picture;
765 763
    }
766 764

  
767
    if (CONFIG_VHOOK)
768
        frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height,
769
                           1000000 * ist->pts / AV_TIME_BASE);
770

  
771 765
    if (picture != picture2)
772 766
        *picture = *picture2;
773 767
    *bufp = buf;
......
1772 1766
                    codec->block_align= 0;
1773 1767
                break;
1774 1768
            case CODEC_TYPE_VIDEO:
1775
                if(using_vhook) {
1776
                    fprintf(stderr,"-vcodec copy and -vhook are incompatible (frames are not decoded)\n");
1777
                    av_exit(1);
1778
                }
1779 1769
                codec->pix_fmt = icodec->pix_fmt;
1780 1770
                codec->width = icodec->width;
1781 1771
                codec->height = icodec->height;
......
2651 2641
        video_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
2652 2642
}
2653 2643

  
2654
#if CONFIG_VHOOK
2655
static void add_frame_hooker(const char *arg)
2656
{
2657
    int argc = 0;
2658
    char *argv[64];
2659
    int i;
2660
    char *args = av_strdup(arg);
2661

  
2662
    using_vhook = 1;
2663

  
2664
    argv[0] = strtok(args, " ");
2665
    while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) {
2666
    }
2667

  
2668
    i = frame_hook_add(argc, argv);
2669

  
2670
    if (i != 0) {
2671
        fprintf(stderr, "Failed to add video hook function: %s\n", arg);
2672
        av_exit(1);
2673
    }
2674
}
2675
#endif
2676

  
2677 2644
static void opt_video_codec(const char *arg)
2678 2645
{
2679 2646
    opt_codec(&video_stream_copy, &video_codec_name, CODEC_TYPE_VIDEO, arg);
......
3840 3807
    { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
3841 3808
    { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
3842 3809
    { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" },
3843
#if CONFIG_VHOOK
3844
    { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" },
3845
#endif
3846 3810
    { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
3847 3811
    { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" },
3848 3812
    { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
libavformat/Makefile
228 228
OBJS-$(CONFIG_LIBNUT_DEMUXER)            += libnut.o riff.o
229 229
OBJS-$(CONFIG_LIBNUT_MUXER)              += libnut.o riff.o
230 230

  
231
OBJS-$(CONFIG_VHOOK)                     += framehook.o
232

  
233 231
# protocols I/O
234 232
OBJS+= avio.o aviobuf.o
235 233

  
libavformat/framehook.c
1
/*
2
 * Video processing hooks
3
 * Copyright (c) 2000, 2001 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
#include <errno.h>
22
#include "config.h"
23
#include "avformat.h"
24
#include "framehook.h"
25

  
26
#if HAVE_DLFCN_H
27
#include <dlfcn.h>
28
#endif
29

  
30

  
31
typedef struct FrameHookEntry {
32
    struct FrameHookEntry *next;
33
    FrameHookConfigureFn Configure;
34
    FrameHookProcessFn Process;
35
    FrameHookReleaseFn Release;
36
    void *ctx;
37
} FrameHookEntry;
38

  
39
static FrameHookEntry *first_hook;
40

  
41
/* Returns 0 on OK */
42
int frame_hook_add(int argc, char *argv[])
43
{
44
    void *loaded;
45
    FrameHookEntry *fhe, **fhep;
46

  
47
    if (argc < 1) {
48
        return ENOENT;
49
    }
50

  
51
    loaded = dlopen(argv[0], RTLD_NOW);
52
    if (!loaded) {
53
        av_log(NULL, AV_LOG_ERROR, "%s\n", dlerror());
54
        return -1;
55
    }
56

  
57
    fhe = av_mallocz(sizeof(*fhe));
58
    if (!fhe) {
59
        return AVERROR(ENOMEM);
60
    }
61

  
62
    fhe->Configure = dlsym(loaded, "Configure");
63
    fhe->Process = dlsym(loaded, "Process");
64
    fhe->Release = dlsym(loaded, "Release");    /* Optional */
65

  
66
    if (!fhe->Process) {
67
        av_log(NULL, AV_LOG_ERROR, "Failed to find Process entrypoint in %s\n", argv[0]);
68
        return AVERROR(ENOENT);
69
    }
70

  
71
    if (!fhe->Configure && argc > 1) {
72
        av_log(NULL, AV_LOG_ERROR, "Failed to find Configure entrypoint in %s\n", argv[0]);
73
        return AVERROR(ENOENT);
74
    }
75

  
76
    if (argc > 1 || fhe->Configure) {
77
        if (fhe->Configure(&fhe->ctx, argc, argv)) {
78
            av_log(NULL, AV_LOG_ERROR, "Failed to Configure %s\n", argv[0]);
79
            return AVERROR(EINVAL);
80
        }
81
    }
82

  
83
    for (fhep = &first_hook; *fhep; fhep = &((*fhep)->next)) {
84
    }
85

  
86
    *fhep = fhe;
87

  
88
    return 0;
89
}
90

  
91
void frame_hook_process(AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
92
{
93
    if (first_hook) {
94
        FrameHookEntry *fhe;
95

  
96
        for (fhe = first_hook; fhe; fhe = fhe->next) {
97
            fhe->Process(fhe->ctx, pict, pix_fmt, width, height, pts);
98
        }
99
    }
100
}
101

  
102
void frame_hook_release(void)
103
{
104
    FrameHookEntry *fhe;
105
    FrameHookEntry *fhenext;
106

  
107
    for (fhe = first_hook; fhe; fhe = fhenext) {
108
        fhenext = fhe->next;
109
        if (fhe->Release)
110
            fhe->Release(fhe->ctx);
111
        av_free(fhe);
112
    }
113

  
114
    first_hook = NULL;
115
}
libavformat/framehook.h
1
/*
2
 * video processing hooks
3
 * copyright (c) 2000, 2001 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
#ifndef AVFORMAT_FRAMEHOOK_H
23
#define AVFORMAT_FRAMEHOOK_H
24

  
25
#warning VHOOK is deprecated. Please help finishing libavfilter instead of wasting your time writing new filters for this crappy filter system.
26

  
27
/*
28
 * Prototypes for interface to .so that implement a video processing hook
29
 */
30

  
31
#include "libavcodec/avcodec.h"
32

  
33
/* Function must be called 'Configure' */
34
typedef int (FrameHookConfigure)(void **ctxp, int argc, char *argv[]);
35
typedef FrameHookConfigure *FrameHookConfigureFn;
36
extern FrameHookConfigure Configure;
37

  
38
/* Function must be called 'Process' */
39
typedef void (FrameHookProcess)(void *ctx, struct AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts);
40
typedef FrameHookProcess *FrameHookProcessFn;
41
extern FrameHookProcess Process;
42

  
43
/* Function must be called 'Release' */
44
typedef void (FrameHookRelease)(void *ctx);
45
typedef FrameHookRelease *FrameHookReleaseFn;
46
extern FrameHookRelease Release;
47

  
48
int frame_hook_add(int argc, char *argv[]);
49
void frame_hook_process(struct AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts);
50
void frame_hook_release(void);
51

  
52
#endif /* AVFORMAT_FRAMEHOOK_H */
vhook/drawtext.c
1
/*
2
 * drawtext.c: print text over the screen
3
 ******************************************************************************
4
 * Options:
5
 * -f <filename>    font filename (MANDATORY!!!)
6
 * -s <pixel_size>  font size in pixels [default 16]
7
 * -b               print background
8
 * -o               outline glyphs (use the bg color)
9
 * -x <pos>         x position ( >= 0) [default 0]
10
 * -y <pos>         y position ( >= 0) [default 0]
11
 * -t <text>        text to print (will be passed to strftime())
12
 *                  MANDATORY: will be used even when -T is used.
13
 *                  in this case, -t will be used if some error
14
 *                  occurs
15
 * -T <filename>    file with the text (re-read every frame)
16
 * -c <#RRGGBB>     foreground color ('internet' way) [default #ffffff]
17
 * -C <#RRGGBB>     background color ('internet' way) [default #000000]
18
 *
19
 ******************************************************************************
20
 * Features:
21
 * - True Type, Type1 and others via FreeType2 library
22
 * - Font kerning (better output)
23
 * - Line Wrap (if the text doesn't fit, the next char go to the next line)
24
 * - Background box
25
 * - Outline
26
 ******************************************************************************
27
 * Author: Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br>
28
 *
29
 * This file is part of FFmpeg.
30
 *
31
 * FFmpeg is free software; you can redistribute it and/or
32
 * modify it under the terms of the GNU Lesser General Public
33
 * License as published by the Free Software Foundation; either
34
 * version 2.1 of the License, or (at your option) any later version.
35
 *
36
 * FFmpeg is distributed in the hope that it will be useful,
37
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39
 * Lesser General Public License for more details.
40
 *
41
 * You should have received a copy of the GNU Lesser General Public
42
 * License along with FFmpeg; if not, write to the Free Software
43
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
44
 */
45

  
46
#define MAXSIZE_TEXT 1024
47

  
48
#include "libavformat/framehook.h"
49

  
50
#include <stdio.h>
51
#include <stdlib.h>
52
#include <fcntl.h>
53
#include <stdarg.h>
54
#include <string.h>
55
#include <unistd.h>
56
#undef time
57
#include <sys/time.h>
58
#include <time.h>
59

  
60
#include <ft2build.h>
61
#include FT_FREETYPE_H
62
#include FT_GLYPH_H
63

  
64
#define SCALEBITS 10
65
#define ONE_HALF  (1 << (SCALEBITS - 1))
66
#define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
67

  
68
#define RGB_TO_YUV(rgb_color, yuv_color) do { \
69
  yuv_color[0] = (FIX(0.29900)    * rgb_color[0] + FIX(0.58700) * rgb_color[1] + FIX(0.11400) * rgb_color[2] + ONE_HALF) >> SCALEBITS; \
70
  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; \
71
  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; \
72
} while (0)
73

  
74
#define COPY_3(dst,src) { \
75
    dst[0]=src[0]; \
76
    dst[1]=src[1]; \
77
    dst[2]=src[2]; \
78
}
79

  
80

  
81

  
82
#define SET_PIXEL(picture, yuv_color, x, y) { \
83
    picture->data[0][ (x) + (y)*picture->linesize[0] ] = yuv_color[0]; \
84
    picture->data[1][ ((x/2) + (y/2)*picture->linesize[1]) ] = yuv_color[1]; \
85
    picture->data[2][ ((x/2) + (y/2)*picture->linesize[2]) ] = yuv_color[2]; \
86
}
87

  
88
#define GET_PIXEL(picture, yuv_color, x, y) { \
89
    yuv_color[0] = picture->data[0][ (x) + (y)*picture->linesize[0] ]; \
90
    yuv_color[1] = picture->data[1][ (x/2) + (y/2)*picture->linesize[1] ]; \
91
    yuv_color[2] = picture->data[2][ (x/2) + (y/2)*picture->linesize[2] ]; \
92
}
93

  
94

  
95
typedef struct {
96
  unsigned char *text;
97
  char *file;
98
  unsigned int x;
99
  unsigned int y;
100
  int bg;
101
  int outline;
102
  unsigned char bgcolor[3]; /* YUV */
103
  unsigned char fgcolor[3]; /* YUV */
104
  FT_Library library;
105
  FT_Face    face;
106
  FT_Glyph   glyphs[ 255 ];
107
  FT_Bitmap  bitmaps[ 255 ];
108
  int        advance[ 255 ];
109
  int        bitmap_left[ 255 ];
110
  int        bitmap_top[ 255 ];
111
  unsigned int glyphs_index[ 255 ];
112
  int        text_height;
113
  int        baseline;
114
  int use_kerning;
115
} ContextInfo;
116

  
117

  
118
void Release(void *ctx)
119
{
120
    if (ctx)
121
        av_free(ctx);
122
}
123

  
124

  
125
static int ParseColor(char *text, unsigned char yuv_color[3])
126
{
127
  char tmp[3];
128
  unsigned char rgb_color[3];
129
  int i;
130

  
131
  tmp[2] = '\0';
132

  
133
  if ((!text) || (strlen(text) != 7) || (text[0] != '#') )
134
    return -1;
135

  
136
  for (i=0; i < 3; i++)
137
    {
138
      tmp[0] = text[i*2+1];
139
      tmp[1] = text[i*2+2];
140

  
141
      rgb_color[i] = strtol(tmp, NULL, 16);
142
    }
143

  
144
  RGB_TO_YUV(rgb_color, yuv_color);
145

  
146
  return 0;
147
}
148

  
149
int Configure(void **ctxp, int argc, char *argv[])
150
{
151
    int c;
152
    int error;
153
    ContextInfo *ci=NULL;
154
    char *font=NULL;
155
    unsigned int size=16;
156
    FT_BBox bbox;
157
    int yMax, yMin;
158
    *ctxp = av_mallocz(sizeof(ContextInfo));
159
    ci = (ContextInfo *) *ctxp;
160

  
161
    /* configure Context Info */
162
    ci->text = NULL;
163
    ci->file = NULL;
164
    ci->x = ci->y = 0;
165
    ci->fgcolor[0]=255;
166
    ci->fgcolor[1]=128;
167
    ci->fgcolor[2]=128;
168
    ci->bgcolor[0]=0;
169
    ci->fgcolor[1]=128;
170
    ci->fgcolor[2]=128;
171
    ci->bg = 0;
172
    ci->outline = 0;
173
    ci->text_height = 0;
174

  
175
    optind = 1;
176
    while ((c = getopt(argc, argv, "f:t:T:x:y:s:c:C:bo")) > 0) {
177
      switch (c) {
178
      case 'f':
179
        font = optarg;
180
        break;
181
      case 't':
182
        ci->text = av_strdup(optarg);
183
        break;
184
      case 'T':
185
        ci->file = av_strdup(optarg);
186
        break;
187
      case 'x':
188
        ci->x = (unsigned int) atoi(optarg);
189
        break;
190
      case 'y':
191
        ci->y = (unsigned int) atoi(optarg);
192
        break;
193
      case 's':
194
        size = (unsigned int) atoi(optarg);
195
        break;
196
      case 'c':
197
        if (ParseColor(optarg, ci->fgcolor) == -1)
198
          {
199
            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);
200
            return -1;
201
          }
202
        break;
203
      case 'C':
204
        if (ParseColor(optarg, ci->bgcolor) == -1)
205
          {
206
            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);
207
            return -1;
208
          }
209
        break;
210
      case 'b':
211
        ci->bg=1;
212
        break;
213
      case 'o':
214
        ci->outline=1;
215
        break;
216
      case '?':
217
        av_log(NULL, AV_LOG_ERROR, "Unrecognized argument '%s'\n", argv[optind]);
218
        return -1;
219
      }
220
    }
221

  
222
    if (!ci->text)
223
      {
224
        av_log(NULL, AV_LOG_ERROR, "No text provided (-t text)\n");
225
        return -1;
226
      }
227

  
228
    if (ci->file)
229
      {
230
        FILE *fp;
231
        if ((fp=fopen(ci->file, "r")) == NULL)
232
          {
233
            av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno));
234
          }
235
        else
236
          {
237
            fclose(fp);
238
          }
239
      }
240

  
241
    if (!font)
242
      {
243
        av_log(NULL, AV_LOG_ERROR, "No font file provided! (-f filename)\n");
244
        return -1;
245
      }
246

  
247
    if ((error = FT_Init_FreeType(&(ci->library))) != 0)
248
      {
249
        av_log(NULL, AV_LOG_ERROR, "Could not load FreeType (error# %d).\n", error);
250
        return -1;
251
      }
252

  
253
    if ((error = FT_New_Face( ci->library, font, 0, &(ci->face) )) != 0)
254
      {
255
        av_log(NULL, AV_LOG_ERROR, "Could not load face: %s  (error# %d).\n", font, error);
256
        return -1;
257
      }
258

  
259
    if ((error = FT_Set_Pixel_Sizes( ci->face, 0, size)) != 0)
260
      {
261
        av_log(NULL, AV_LOG_ERROR, "Could not set font size to %d pixels (error# %d).\n", size, error);
262
        return -1;
263
      }
264

  
265
    ci->use_kerning = FT_HAS_KERNING(ci->face);
266

  
267
    /* load and cache glyphs */
268
    yMax = -32000;
269
    yMin =  32000;
270
    for (c=0; c < 256; c++)
271
      {
272
        /* Load char */
273
        error = FT_Load_Char( ci->face, (unsigned char) c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME );
274
        if (error) continue;  /* ignore errors */
275

  
276
        /* Save bitmap */
277
        ci->bitmaps[c] = ci->face->glyph->bitmap;
278
        /* Save bitmap left */
279
        ci->bitmap_left[c] = ci->face->glyph->bitmap_left;
280
        /* Save bitmap top */
281
        ci->bitmap_top[c] = ci->face->glyph->bitmap_top;
282

  
283
        /* Save advance */
284
        ci->advance[c] = ci->face->glyph->advance.x >> 6;
285

  
286
        /* Save glyph */
287
        error = FT_Get_Glyph( ci->face->glyph, &(ci->glyphs[c]) );
288
        /* Save glyph index */
289
        ci->glyphs_index[c] = FT_Get_Char_Index( ci->face, (unsigned char) c );
290

  
291
        /* Measure text height to calculate text_height (or the maximum text height) */
292
        FT_Glyph_Get_CBox( ci->glyphs[ c ], ft_glyph_bbox_pixels, &bbox );
293
        if (bbox.yMax > yMax)
294
          yMax = bbox.yMax;
295
        if (bbox.yMin < yMin)
296
          yMin = bbox.yMin;
297

  
298
      }
299

  
300
    ci->text_height = yMax - yMin;
301
    ci->baseline = yMax;
302

  
303
    return 0;
304
}
305

  
306

  
307

  
308

  
309
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)
310
{
311
  int r, c;
312
  int spixel, dpixel[3], in_glyph=0;
313

  
314
  if (bitmap->pixel_mode == ft_pixel_mode_mono)
315
    {
316
      in_glyph = 0;
317
      for (r=0; (r < bitmap->rows) && (r+y < height); r++)
318
        {
319
          for (c=0; (c < bitmap->width) && (c+x < width); c++)
320
            {
321
              /* pixel in the picture (destination) */
322
              GET_PIXEL(picture, dpixel, (c+x), (y+r));
323

  
324
              /* pixel in the glyph bitmap (source) */
325
              spixel = bitmap->buffer[r*bitmap->pitch +c/8] & (0x80>>(c%8));
326

  
327
              if (spixel)
328
                COPY_3(dpixel, yuv_fgcolor);
329

  
330
              if (outline)
331
                {
332
                  /* border detection: */
333
                  if ( (!in_glyph) && (spixel) )
334
                    /* left border detected */
335
                    {
336
                      in_glyph = 1;
337
                      /* draw left pixel border */
338
                      if (c-1 >= 0)
339
                        SET_PIXEL(picture, yuv_bgcolor, (c+x-1), (y+r));
340
                    }
341
                  else if ( (in_glyph) && (!spixel) )
342
                    /* right border detected */
343
                    {
344
                      in_glyph = 0;
345
                      /* 'draw' right pixel border */
346
                      COPY_3(dpixel, yuv_bgcolor);
347
                    }
348

  
349
                  if (in_glyph)
350
                    /* see if we have a top/bottom border */
351
                    {
352
                      /* top */
353
                      if ( (r-1 >= 0) && (! bitmap->buffer[(r-1)*bitmap->pitch +c/8] & (0x80>>(c%8))) )
354
                        /* we have a top border */
355
                        SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r-1));
356

  
357
                      /* bottom */
358
                      if ( (r+1 < height) && (! bitmap->buffer[(r+1)*bitmap->pitch +c/8] & (0x80>>(c%8))) )
359
                        /* we have a bottom border */
360
                        SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r+1));
361

  
362
                    }
363
                }
364

  
365
              SET_PIXEL(picture, dpixel, (c+x), (y+r));
366
            }
367
        }
368
    }
369
}
370

  
371

  
372
static inline void draw_box(AVPicture *picture, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_color[3])
373
{
374
  int i, j;
375

  
376
  for (j = 0; (j < height); j++)
377
    for (i = 0; (i < width); i++)
378
      {
379
        SET_PIXEL(picture, yuv_color, (i+x), (y+j));
380
      }
381

  
382
}
383

  
384

  
385

  
386

  
387
void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
388
{
389
  ContextInfo *ci = (ContextInfo *) ctx;
390
  FT_Face face = ci->face;
391
  FT_GlyphSlot  slot = face->glyph;
392
  unsigned char *text = ci->text;
393
  unsigned char c;
394
  int x = 0, y = 0, i=0, size=0;
395
  unsigned char buff[MAXSIZE_TEXT];
396
  unsigned char tbuff[MAXSIZE_TEXT];
397
  time_t now = time(0);
398
  int str_w, str_w_max;
399
  FT_Vector pos[MAXSIZE_TEXT];
400
  FT_Vector delta;
401

  
402
  if (ci->file)
403
    {
404
      int fd = open(ci->file, O_RDONLY);
405

  
406
      if (fd < 0)
407
        {
408
          text = ci->text;
409
          av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno));
410
        }
411
      else
412
        {
413
          int l = read(fd, tbuff, sizeof(tbuff) - 1);
414

  
415
          if (l >= 0)
416
            {
417
              tbuff[l] = 0;
418
              text = tbuff;
419
            }
420
          else
421
            {
422
              text = ci->text;
423
              av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be read. Using text provided with -t switch: %s", strerror(errno));
424
            }
425
          close(fd);
426
        }
427
    }
428
  else
429
    {
430
      text = ci->text;
431
    }
432

  
433
  strftime(buff, sizeof(buff), text, localtime(&now));
434

  
435
  text = buff;
436

  
437
  size = strlen(text);
438

  
439

  
440

  
441

  
442
  /* measure string size and save glyphs position*/
443
  str_w = str_w_max = 0;
444
  x = ci->x;
445
  y = ci->y;
446
  for (i=0; i < size; i++)
447
    {
448
      c = text[i];
449

  
450
      /* kerning */
451
      if ( (ci->use_kerning) && (i > 0) && (ci->glyphs_index[c]) )
452
        {
453
          FT_Get_Kerning( ci->face,
454
                          ci->glyphs_index[ text[i-1] ],
455
                          ci->glyphs_index[c],
456
                          ft_kerning_default,
457
                          &delta );
458

  
459
          x += delta.x >> 6;
460
        }
461

  
462
      if (( (x + ci->advance[ c ]) >= width ) || ( c == '\n' ))
463
        {
464
          str_w = width - ci->x - 1;
465

  
466
          y += ci->text_height;
467
          x = ci->x;
468
        }
469

  
470

  
471
      /* save position */
472
      pos[i].x = x + ci->bitmap_left[c];
473
      pos[i].y = y - ci->bitmap_top[c] + ci->baseline;
474

  
475

  
476
      x += ci->advance[c];
477

  
478

  
479
      if (str_w > str_w_max)
480
        str_w_max = str_w;
481

  
482
    }
483

  
484

  
485

  
486

  
487
  if (ci->bg)
488
    {
489
      /* Check if it doesn't pass the limits */
490
      if ( str_w_max + ci->x >= width )
491
        str_w_max = width - ci->x - 1;
492
      if ( y >= height )
493
        y = height - 1 - 2*ci->y;
494

  
495
      /* Draw Background */
496
      draw_box( picture, ci->x, ci->y, str_w_max, y - ci->y, ci->bgcolor );
497
    }
498

  
499

  
500

  
501
  /* Draw Glyphs */
502
  for (i=0; i < size; i++)
503
    {
504
      c = text[i];
505

  
506
      if (
507
          ( (c == '_') && (text == ci->text) ) || /* skip '_' (consider as space)
508
                                                     IF text was specified in cmd line
509
                                                     (which doesn't like nested quotes)  */
510
          ( c == '\n' ) /* Skip new line char, just go to new line */
511
          )
512
        continue;
513

  
514
        /* now, draw to our target surface */
515
        draw_glyph( picture,
516
                    &(ci->bitmaps[ c ]),
517
                    pos[i].x,
518
                    pos[i].y,
519
                    width,
520
                    height,
521
                    ci->fgcolor,
522
                    ci->bgcolor,
523
                    ci->outline );
524

  
525
      /* increment pen position */
526
      x += slot->advance.x >> 6;
527
    }
528

  
529

  
530
}
531

  
vhook/fish.c
1
/*
2
 * Fish Detector Hook
3
 * Copyright (c) 2002 Philip Gladstone
4
 *
5
 * This file implements a fish detector. It is used to see when a
6
 * goldfish passes in front of the camera. It does this by counting
7
 * the number of input pixels that fall within a particular HSV
8
 * range.
9
 *
10
 * It takes a multitude of arguments:
11
 *
12
 * -h <num>-<num>    the range of H values that are fish
13
 * -s <num>-<num>    the range of S values that are fish
14
 * -v <num>-<num>    the range of V values that are fish
15
 * -z                zap all non-fish values to black
16
 * -l <num>          limit the number of saved files to <num>
17
 * -i <num>          only check frames every <num> seconds
18
 * -t <num>          the threshold for the amount of fish pixels (range 0-1)
19
 * -d                turn debugging on
20
 * -D <directory>    where to put the fish images
21
 *
22
 * This file is part of FFmpeg.
23
 *
24
 * FFmpeg is free software; you can redistribute it and/or
25
 * modify it under the terms of the GNU Lesser General Public
26
 * License as published by the Free Software Foundation; either
27
 * version 2.1 of the License, or (at your option) any later version.
28
 *
29
 * FFmpeg is distributed in the hope that it will be useful,
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff