[FFmpeg-devel] [PATCH] libcaca output device
Stefano Sabatini
stefasab at gmail.com
Fri Jul 20 11:22:12 CEST 2012
On date Friday 2012-07-20 02:08:21 +0000, Paul B Mahol encoded:
>
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> configure | 12 ++
> doc/outdevs.texi | 52 ++++++++++
> libavdevice/Makefile | 1 +
> libavdevice/alldevices.c | 1 +
> libavdevice/caca.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 318 insertions(+), 0 deletions(-)
> create mode 100644 libavdevice/caca.c
>
> diff --git a/configure b/configure
> index 300f128..2c5d62a 100755
> --- a/configure
> +++ b/configure
> @@ -1230,6 +1230,7 @@ HAVE_LIST="
> jack_port_get_latency_range
> kbhit
> ldbrx
> + libcaca
> libdc1394_1
> libdc1394_2
> llrint
> @@ -1697,6 +1698,7 @@ fbdev_indev_deps="linux_fb_h"
> iec61883_indev_deps="libiec61883"
> jack_indev_deps="jack_jack_h sem_timedwait"
> lavfi_indev_deps="avfilter"
> +libcaca_outdev_deps="libcaca"
> libcdio_indev_deps="libcdio"
> libdc1394_indev_deps="libdc1394"
> libv4l2_indev_deps="libv4l2"
> @@ -3363,6 +3365,14 @@ if enabled libdc1394; then
> die "ERROR: No version of libdc1394 found "
> fi
>
> +LIBCACA_CONFIG="${cross_prefix}caca-config"
> +if "${LIBCACA_CONFIG}" --version > /dev/null 2>&1; then
> + libcaca_cflags=$("${LIBCACA_CONFIG}" --cflags)
> + libcaca_libs=$("${LIBCACA_CONFIG}" --libs)
> + enable libcaca
> +fi
> +enabled libcaca && add_cflags $libcaca_cflags && add_extralibs $libcaca_libs
> +
The alternative to auto-detection is to require the user to specify
--enable-libcaca, which is consistent with the use of all the other
libraries (but libsdl) and thus recommended (libcaca is not special).
Also I suggest two simpler alternatives to this:
enabled libcaca && require_pkg_config caca caca.h caca_create_canvas
or even simpler:
enabled libcaca && require libcaca caca.h caca_create_canvas -lcaca
provided that libcaca has no complex dependencies.
> SDL_CONFIG="${cross_prefix}sdl-config"
> if check_pkg_config sdl SDL_events.h SDL_PollEvent; then
> check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x010201" $sdl_cflags &&
> @@ -3817,6 +3827,8 @@ HOSTLDFLAGS=$host_ldflags
> HOSTLIBS=$host_libs
> TARGET_EXEC=$target_exec
> TARGET_PATH=$target_path
> +CACA_LIBS=$libcaca_libs
> +CACA_CFLAGS=$libcaca_cflags
Is this still required?
> SDL_LIBS=$sdl_libs
> SDL_CFLAGS=$sdl_cflags
> LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD
> diff --git a/doc/outdevs.texi b/doc/outdevs.texi
> index 8034a22..71e4986 100644
> --- a/doc/outdevs.texi
> +++ b/doc/outdevs.texi
> @@ -22,6 +22,58 @@ A description of the currently available output devices follows.
>
> ALSA (Advanced Linux Sound Architecture) output device.
>
> + at section caca
> +
> +CACA output device.
> +
> +This output devices allows to show a video stream in CACA window.
> +Only one CACA window is allowed per application, so you can
> +have only one instance of this output device in an application.
> +
> +To enable this output device you need libcaca installed on your system
> +when configuring your build.
> +libcaca is a graphics library that outputs text instead of pixels.
> +
> + at subsection Options
> +
> + at table @option
> +
> + at item window_title
> +Set the CACA window title, if not specified default to the filename
> +specified for the output device.
> +
> + at item window_size
> +Set the CACA window size, can be a string of the form
> + at var{width}x at var{height} or a video size abbreviation.
> +If not specified it defaults to the size of the input video.
> +
> + at item driver
> +Set display driver.
> +
> + at item algorithm
> +Set dithering algorithm. Dithering is necessary
> +because the picture being rendered has usually far more colours than
> +the available palette.
> +
> + at item antialias
> +Set antialias method. Antialiasing smoothens the rendered
> +image and avoids the commonly seen staircase effect.
> +
> + at item charset
> +Set which characters are going to be used when rendering text.
> +
> + at item colors
> +Set colors to be used when rendering text.
> + at end table
> +
> + at subsection Examples
> +
> +The following command shows the @command{ffmpeg} output is an
> +CACA window, forcing its size to 80x25:
> + at example
> +ffmpeg -i INPUT -vcodec rawvideo -pix_fmt rgb24 -window_size 80x25 -f caca -
> + at end example
> +
> @section oss
>
> OSS (Open Sound System) output device.
> diff --git a/libavdevice/Makefile b/libavdevice/Makefile
> index 4759a82..8f6f843 100644
> --- a/libavdevice/Makefile
> +++ b/libavdevice/Makefile
> @@ -16,6 +16,7 @@ OBJS-$(CONFIG_ALSA_INDEV) += alsa-audio-common.o \
> OBJS-$(CONFIG_ALSA_OUTDEV) += alsa-audio-common.o \
> alsa-audio-enc.o
> OBJS-$(CONFIG_BKTR_INDEV) += bktr.o
> +OBJS-$(CONFIG_CACA_OUTDEV) += caca.o
> OBJS-$(CONFIG_DSHOW_INDEV) += dshow.o dshow_enummediatypes.o \
> dshow_enumpins.o dshow_filter.o \
> dshow_pin.o dshow_common.o
> diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c
> index 2a0bffb..092e6c5 100644
> --- a/libavdevice/alldevices.c
> +++ b/libavdevice/alldevices.c
> @@ -40,6 +40,7 @@ void avdevice_register_all(void)
> /* devices */
> REGISTER_INOUTDEV (ALSA, alsa);
> REGISTER_INDEV (BKTR, bktr);
> + REGISTER_OUTDEV (CACA, caca);
> REGISTER_INDEV (DSHOW, dshow);
> REGISTER_INDEV (DV1394, dv1394);
> REGISTER_INDEV (FBDEV, fbdev);
> diff --git a/libavdevice/caca.c b/libavdevice/caca.c
> new file mode 100644
> index 0000000..09fe192
> --- /dev/null
> +++ b/libavdevice/caca.c
> @@ -0,0 +1,252 @@
> +/*
> + * Copyright (c) 2011 Paul B Mahol
> + *
> + * 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 <caca.h>
> +#include "libavutil/opt.h"
> +#include "libavutil/pixdesc.h"
> +#include "avdevice.h"
> +
> +typedef struct {
> + AVClass *class;
> + AVFormatContext *ctx;
> + char *window_title;
> + int window_width, window_height;
> +
> + caca_canvas_t *canvas;
> + caca_display_t *display;
> + caca_dither_t *dither;
> +
> + char *algorithm, *antialias;
> + char *charset, *colors;
> + char *driver;
> +
> + int list_antialias, list_algorithms;
> + int list_charsets, list_colors;
> + int list_drivers;
> +
> +} CACAContext;
> +
> +static int caca_write_trailer(AVFormatContext *s)
> +{
> + CACAContext *c = s->priv_data;
> +
> + av_freep(&c->window_title);
> +
> + caca_free_dither(c->dither);
> + caca_free_display(c->display);
> + caca_free_canvas(c->canvas);
> + return 0;
> +}
> +
> +static void available_drivers(CACAContext *c)
Nit: list_available_drivers
> +{
> + const char *const *drivers = caca_get_display_driver_list();
> + int i;
> +
> + av_log(c->ctx, AV_LOG_INFO, "Available drivers:\n");
> + for (i = 0; drivers[i]; i += 2)
> + av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", drivers[i], drivers[i + 1]);
> +}
> +
> +static void available_colors(CACAContext *c)
> +{
> + const char *const *color = caca_get_dither_color_list(c->dither);
> + int i;
> +
> + av_log(c->ctx, AV_LOG_INFO, "Available colors:\n");
> + for (i = 0; color[i]; i += 2)
> + av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", color[i], color[i + 1]);
> +}
> +
> +static void available_charsets(CACAContext *c)
> +{
> + const char *const *charset = caca_get_dither_charset_list(c->dither);
> + int i;
> +
> + av_log(c->ctx, AV_LOG_INFO, "Available charsets:\n");
> + for (i = 0; charset[i]; i += 2)
> + av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", charset[i], charset[i + 1]);
> +}
> +
> +static void available_algorithms(CACAContext *c)
> +{
> + const char *const *algorithm = caca_get_dither_algorithm_list(c->dither);
> + int i;
> +
> + av_log(c->ctx, AV_LOG_INFO, "Available dithering algorithms:\n");
> + for (i = 0; algorithm[i]; i += 2)
> + av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", algorithm[i], algorithm[i + 1]);
> +}
> +
> +static void available_antialias(CACAContext *c)
> +{
> + const char *const *antialias = caca_get_dither_antialias_list(c->dither);
> + int i;
> +
> + av_log(c->ctx, AV_LOG_INFO, "Available antialias methods:\n");
> + for (i = 0; antialias[i]; i += 2)
> + av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", antialias[i], antialias[i + 1]);
> +}
This can be macrotized:
#define DEFINE_LIST_DITHER(thing, things_str) \
static void list_available_dither_##thing(CACAContext *c) \
{ \
const char *const *thing = caca_get_dither_##thing##_list(c->dither); \
int i; \
\
av_log(c->ctx, AV_LOG_INFO, "Available dither " things_str " methods:\n"); \
...
DEFINE_LIST_DITHER(color, "colors");
...
DEFINE_LIST_DITHER(antialias, "antialias methods");
or factorized using templating.
> +
> +static int caca_write_header(AVFormatContext *s)
> +{
> + CACAContext *c = s->priv_data;
> + AVStream *st = s->streams[0];
> + AVCodecContext *encctx = st->codec;
> + int ret, bpp;
> +
> + c->ctx = s;
> +
> + if (c->list_drivers)
> + available_drivers(c);
> + if (c->list_colors)
> + available_colors(c);
> + if (c->list_charsets)
> + available_charsets(c);
> + if (c->list_algorithms)
> + available_algorithms(c);
> + if (c->list_antialias)
> + available_antialias(c);
To reduce the number of options, you could have a -list_drivers and
-list_dither thing option, working like this:
int log_dither_list(CACAContext *caca, const char *thing)
{
...
{ "antialias", caca_get_dither_antialias_list, "antialias methods" };
...
for entries[j]
if (!strcmp(entries[i].thing)) {
const char *const *list = entries[i].list_fn(caca);
for (j = 0; list[j]; j += 2)
av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", list[j], list[j + 1]);
return AVERROR_EXIT;
}
log error
return AVERROR(EINVAL);
}
[...]
--
FFmpeg = Foolish and Fundamental Meaningless Proud Experimenting Guru
More information about the ffmpeg-devel
mailing list