[FFmpeg-devel] [PATCH] libcaca output device
Stefano Sabatini
stefasab at gmail.com
Sat Jul 21 01:25:32 CEST 2012
On date Friday 2012-07-20 18:12:45 +0000, Paul B Mahol encoded:
>
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> configure | 6 ++
> doc/outdevs.texi | 52 +++++++++++
> libavdevice/Makefile | 1 +
> libavdevice/alldevices.c | 1 +
> libavdevice/caca.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 282 insertions(+), 0 deletions(-)
> create mode 100644 libavdevice/caca.c
>
> diff --git a/configure b/configure
> index bc46bb7..3b4d9bc 100755
> --- a/configure
> +++ b/configure
> @@ -173,6 +173,8 @@ External library support:
> --enable-libaacplus enable AAC+ encoding via libaacplus [no]
> --enable-libass enable libass subtitles rendering [no]
> --enable-libbluray enable BluRay reading using libbluray [no]
> + --enable-libcaca enable caca output device using libcaca
> + graphics library [no]
Nit: simpler and on a line (more grep-friendly):
--enable-libcaca enable textual display using libcaca [no]
> --enable-libcelt enable CELT decoding via libcelt [no]
> --enable-libcdio enable audio CD grabbing with libcdio
> --enable-libdc1394 enable IIDC-1394 grabbing using libdc1394
> @@ -1051,6 +1053,7 @@ CONFIG_LIST="
> libaacplus
> libass
> libbluray
> + libcaca
> libcdio
> libcelt
> libdc1394
> @@ -1693,6 +1696,7 @@ w64_demuxer_deps="wav_demuxer"
> alsa_indev_deps="alsa_asoundlib_h snd_pcm_htimestamp"
> alsa_outdev_deps="alsa_asoundlib_h"
> bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h"
> +caca_outdev_deps="libcaca"
> dshow_indev_deps="IBaseFilter"
> dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid"
> dv1394_indev_deps="dv1394 dv_demuxer"
> @@ -3312,6 +3316,7 @@ enabled libbluray && require libbluray libbluray/bluray.h bd_open -lbluray
> enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 &&
> { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 ||
> die "ERROR: libcelt version must be >= 0.11.0."; }
> +enabled libcaca && require_pkg_config caca caca.h caca_create_canvas
> enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac
> enabled libfdk_aac && require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac
> enabled libfreetype && require_pkg_config freetype2 "ft2build.h freetype/freetype.h" FT_Init_FreeType
> @@ -3688,6 +3693,7 @@ echo "frei0r enabled ${frei0r-no}"
> echo "gnutls enabled ${gnutls-no}"
> echo "libaacplus enabled ${libaacplus-no}"
> echo "libass enabled ${libass-no}"
> +echo "libcaca enabled ${libcaca-no}"
> echo "libcdio support ${libcdio-no}"
> echo "libcelt enabled ${libcelt-no}"
> echo "libdc1394 support ${libdc1394-no}"
> 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.
To enable this output device you need to configure FFmpeg with
@code{--enable-libcaca}.
> +libcaca is a graphics library that outputs text instead of pixels.
Maybe add a link to the project (kitch) website: http://caca.zoy.org/wiki/libcaca
> +
> + 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.
Missing list_drivers and list_dither options.
> + 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..f873128
> --- /dev/null
> +++ b/libavdevice/caca.c
> @@ -0,0 +1,222 @@
> +/*
> + * Copyright (c) 2011 Paul B Mahol
Is that so old?
> + *
> + * 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 CACAContext {
> + 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;
Nit++: maybe on a line
> +
> + char *list_dither;
> + 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 list_available_drivers(CACAContext *c)
Nit++: list_drivers is shorter and as meaningful, same below.
> +{
> + 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]);
> +}
> +
> #define DEFINE_LIST_DITHER(thing, thing_str) \
You could pass thing and things in order to avoid singular/plural
mismatches in the function names (list_dither_color -> list_dither_colors):
stativ void list_dither_## things(...)
...
av_log(c->ctx, AV_LOG_INFO, "Available " #things ":\n");
> +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 %s:\n", thing_str); \
> + for (i = 0; thing[i]; i += 2) \
> + av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", thing[i], thing[i + 1]); \
> +}
> +
> +
> +DEFINE_LIST_DITHER(color, "colors");
> +DEFINE_LIST_DITHER(charset, "charsets");
> +DEFINE_LIST_DITHER(algorithm, "algorithms");
> +DEFINE_LIST_DITHER(antialias, "antialias");
> +
> +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) {
> + list_available_drivers(c);
> + return AVERROR_EXIT;
> + }
> + if (c->list_dither) {
> + if (!strcmp(c->list_dither, "color"))
> + list_available_dither_color(c);
should all them take plural form?
I mean "-list_dither colors" seems more natural than -list_dither color.
> + else if (!strcmp(c->list_dither, "charset"))
> + list_available_dither_charset(c);
> + else if (!strcmp(c->list_dither, "algorithm"))
> + list_available_dither_algorithm(c);
> + else if (!strcmp(c->list_dither, "antialias"))
> + list_available_dither_antialias(c);
else {
av_log(s, AV_LOG_ERROR, "Invalid value '%s' for 'list_dither' option\n");
return AVERROR(EINVAL);
}
> + return AVERROR_EXIT;
> + }
> +
> +
nit+10!: double empty line
> + if ( s->nb_streams > 1
> + || encctx->codec_type != AVMEDIA_TYPE_VIDEO
> + || encctx->codec_id != CODEC_ID_RAWVIDEO) {
> + av_log(s, AV_LOG_ERROR, "Only supports one rawvideo stream\n");
> + return AVERROR(EINVAL);
> + }
> +
> + if (encctx->pix_fmt != PIX_FMT_RGB24) {
> + av_log(s, AV_LOG_ERROR,
> + "Unsupported pixel format '%s', choose rgb24\n",
> + av_get_pix_fmt_name(encctx->pix_fmt));
> + return AVERROR(EINVAL);
> + }
> +
> + if (!c->window_width || !c->window_height) {
> + c->window_width = encctx->width;
> + c->window_height = encctx->height;
> + }
> + c->canvas = caca_create_canvas(c->window_width, c->window_height);
> + if (!c->canvas) {
> + av_log(s, AV_LOG_ERROR, "Failed to create canvas\n");
> + return AVERROR(errno);
> + }
> +
> + c->display = caca_create_display_with_driver(c->canvas, c->driver);
> + if (!c->display) {
> + av_log(s, AV_LOG_ERROR, "Failed to create display\n");
> + list_available_drivers(c);
> + caca_free_canvas(c->canvas);
> + return AVERROR(errno);
> + }
> +
> + bpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[encctx->pix_fmt]);
> + c->dither = caca_create_dither(bpp, encctx->width, encctx->height,
> + bpp * encctx->width / 8,
> + 0x0000ff, 0x00ff00, 0xff0000, 0);
> + if (!c->dither) {
> + av_log(s, AV_LOG_ERROR, "Failed to create dither\n");
> + ret = AVERROR(errno);
> + goto fail;
> + }
> +
> + ret = caca_set_dither_algorithm(c->dither, c->algorithm);
> + ret += caca_set_dither_antialias(c->dither, c->antialias);
> + ret += caca_set_dither_charset(c->dither, c->charset);
> + ret += caca_set_dither_color(c->dither, c->colors);
nit+++: vertical align
[...]
Looks cool otherwise (it was in my mental list of fancy todos since a
while). I'll try to come up with a libaa outdev if you are not already
working on it.
--
FFmpeg = Forgiving and Frightening Mythic Power Elected God
More information about the ffmpeg-devel
mailing list