[FFmpeg-devel] [PATCH] lavf: add libquvi demuxer.

Stefano Sabatini stefasab at gmail.com
Wed Apr 10 19:22:31 CEST 2013


On date Thursday 2013-04-04 13:46:29 +0200, Clément Bœsch encoded:
> On Thu, Apr 04, 2013 at 12:44:42PM +0200, Nicolas George wrote:
> > Le quintidi 15 germinal, an CCXXI, Clement Boesch a écrit :
> > > From ae193b28011e6354b57c0c3c47af00c53c07a6a5 Mon Sep 17 00:00:00 2001
> > > From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <ubitux at gmail.com>
> > > Date: Thu, 4 Apr 2013 08:22:32 +0200
> > > Subject: [PATCH] lavf: add libquvi demuxer.
> > > 
> > > ---
> > >  Changelog                |   1 +
> > >  configure                |   4 ++
> > >  libavformat/Makefile     |   1 +
> > >  libavformat/allformats.c |   1 +
> > >  libavformat/libquvi.c    | 145 +++++++++++++++++++++++++++++++++++++++++++++++
> > >  libavformat/version.h    |   2 +-
> > >  6 files changed, 153 insertions(+), 1 deletion(-)
> > >  create mode 100644 libavformat/libquvi.c
> > 
> > No documentation?
> > 
> 
> Laziness hits me badly every day. Small documentation added.
> 
> [...]
> > > +    rc = quvi_getprop(m, QUVIPROP_MEDIAURL, &media_url);
> > > +    if (rc != QUVI_OK)
> > > +        goto quvi_fail;
> > > +
> > 
> > > +    ret = avformat_open_input(&qc->fmtctx, media_url, NULL, NULL);
> > 
> > Some services, including youtube depending on the phase of the moon, use the
> > user-agent / the referrer / cookies to perform filtering. Will they work?
> > 
> 
> No they won't; I haven't found a simpler and sexy way to do that. Patch
> and suggestions welcome (it seems I can't just move the metadata from the
> current to the internal format context). Note that they are not needed
> most of the time; ffplay 'http://youtube.com/...' works out of the box.
> 
> [...]
> > > +AVInputFormat ff_libquvi_demuxer = {
> > > +    .name           = "libquvi",
> > > +    .long_name      = NULL_IF_CONFIG_SMALL("libquvi demuxer"),
> > > +    .priv_data_size = sizeof(LibQuviContext),
> > > +    .read_probe     = libquvi_probe,
> > > +    .read_header    = libquvi_read_header,
> > > +    .read_packet    = libquvi_read_packet,
> > > +    .read_close     = libquvi_close,
> > > +    .read_seek      = libquvi_read_seek,
> > > +    .priv_class     = &libquvi_context_class,
> > 
> > AVFMT_NOFILE?
> > 
> 
> Added.
> 
> -- 
> Clément B.

> From 2219761d20f518a5910f432f9f2f61f2f7e941db Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <ubitux at gmail.com>
> Date: Thu, 4 Apr 2013 08:22:32 +0200
> Subject: [PATCH] lavf: add libquvi demuxer.
> 
> ---
>  Changelog                |   1 +
>  configure                |   4 ++
>  doc/demuxers.texi        |  12 ++++
>  libavformat/Makefile     |   1 +
>  libavformat/allformats.c |   1 +
>  libavformat/libquvi.c    | 146 +++++++++++++++++++++++++++++++++++++++++++++++
>  libavformat/version.h    |   2 +-
>  7 files changed, 166 insertions(+), 1 deletion(-)
>  create mode 100644 libavformat/libquvi.c
> 
> diff --git a/Changelog b/Changelog
> index 5faa414..1ee0d4a 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -16,6 +16,7 @@ version <next>:
>    filtergraph description to be read from a file
>  - OpenCL support
>  - audio phaser filter
> +- libquvi demuxer
>  
>  
>  version 1.2:
> diff --git a/configure b/configure
> index 4b46007..c36c09d 100755
> --- a/configure
> +++ b/configure
> @@ -215,6 +215,7 @@ External library support:
>    --enable-libopenjpeg     enable JPEG 2000 de/encoding via OpenJPEG [no]
>    --enable-libopus         enable Opus decoding via libopus [no]
>    --enable-libpulse        enable Pulseaudio input via libpulse [no]
> +  --enable-libquvi         enable quvi input via libquvi [no]
>    --enable-librtmp         enable RTMP[E] support via librtmp [no]
>    --enable-libschroedinger enable Dirac de/encoding via libschroedinger [no]
>    --enable-libsoxr         enable Include libsoxr resampling [no]
> @@ -1163,6 +1164,7 @@ EXTERNAL_LIBRARY_LIST="
>      libopenjpeg
>      libopus
>      libpulse
> +    libquvi
>      librtmp
>      libschroedinger
>      libsoxr
> @@ -1954,6 +1956,7 @@ libopenjpeg_encoder_deps="libopenjpeg"
>  libopus_decoder_deps="libopus"
>  libopus_encoder_deps="libopus"
>  libopus_encoder_select="audio_frame_queue"
> +libquvi_demuxer_deps="libquvi"
>  libschroedinger_decoder_deps="libschroedinger"
>  libschroedinger_encoder_deps="libschroedinger"
>  libspeex_decoder_deps="libspeex"
> @@ -3970,6 +3973,7 @@ enabled libopenjpeg && { check_lib openjpeg-1.5/openjpeg.h opj_version -lopenjpe
>                           die "ERROR: libopenjpeg not found"; }
>  enabled libopus    && require_pkg_config opus opus_multistream.h opus_multistream_decoder_create
>  enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_new
> +enabled libquvi    && require_pkg_config libquvi quvi/quvi.h quvi_init
>  enabled librtmp    && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket
>  enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init
>  enabled libsoxr    && require  libsoxr soxr.h soxr_create -lsoxr
> diff --git a/doc/demuxers.texi b/doc/demuxers.texi
> index 03d4f59..c75e1ab 100644
> --- a/doc/demuxers.texi
> +++ b/doc/demuxers.texi
> @@ -103,6 +103,18 @@ probed and 0 otherwise.
>  
>  @end table
>  

> + at section libquvi
> +
> +Play media from Internet services using the quvi project.
> +
> +The demuxer accepts a @option{format} option to request a specific quality. It
> +is by default set to @var{best}.
> +
> +See @url{http://quvi.sourceforge.net/} for more information.

Missing option description and some examples, sorely needed since
libquvi documentation is not so complete nor easy to find.

> +
> +FFmpeg needs to be built with @code{--enable-libquvi} for this demuxer to be
> +enabled.
> +
>  @section image2
>  
>  Image file demuxer.
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index bc6ea16..470e7f3 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -405,6 +405,7 @@ OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER)      += yuv4mpeg.o
>  OBJS-$(CONFIG_LIBMODPLUG_DEMUXER)        += libmodplug.o
>  OBJS-$(CONFIG_LIBNUT_DEMUXER)            += libnut.o
>  OBJS-$(CONFIG_LIBNUT_MUXER)              += libnut.o
> +OBJS-$(CONFIG_LIBQUVI_DEMUXER)           += libquvi.o
>  OBJS-$(CONFIG_LIBRTMP)                   += librtmp.o
>  
>  # protocols I/O
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index 8c746ff..8663f81 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -338,4 +338,5 @@ void av_register_all(void)
>      REGISTER_PROTOCOL(LIBRTMPS,         librtmps);
>      REGISTER_PROTOCOL(LIBRTMPT,         librtmpt);
>      REGISTER_PROTOCOL(LIBRTMPTE,        librtmpte);
> +    REGISTER_DEMUXER (LIBQUVI,          libquvi);
>  }
> diff --git a/libavformat/libquvi.c b/libavformat/libquvi.c
> new file mode 100644
> index 0000000..42ad35e
> --- /dev/null
> +++ b/libavformat/libquvi.c
> @@ -0,0 +1,146 @@
> +/*
> + * Copyright (c) 2013 Clément Bœsch
> + *
> + * 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 <quvi/quvi.h>
> +
> +#include "libavformat/avformat.h"
> +#include "libavformat/internal.h"
> +#include "libavutil/opt.h"
> +
> +typedef struct {
> +    const AVClass *class;
> +    char *format;
> +    AVFormatContext *fmtctx;
> +} LibQuviContext;
> +
> +#define OFFSET(x) offsetof(LibQuviContext, x)
> +#define FLAGS AV_OPT_FLAG_DECODING_PARAM
> +static const AVOption libquvi_options[] = {
> +    { "format", "request specific format", OFFSET(format), AV_OPT_TYPE_STRING, {.str="best"}, .flags = FLAGS },
> +    { NULL }
> +};
> +
> +static const AVClass libquvi_context_class = {
> +    .class_name     = "libquvi",
> +    .item_name      = av_default_item_name,
> +    .option         = libquvi_options,
> +    .version        = LIBAVUTIL_VERSION_INT,
> +};
> +
> +static int libquvi_close(AVFormatContext *s)
> +{
> +    LibQuviContext *qc = s->priv_data;
> +    if (qc->fmtctx)
> +        avformat_close_input(&qc->fmtctx);
> +    return 0;
> +}
> +
> +static int libquvi_read_header(AVFormatContext *s)
> +{
> +    int i, ret;
> +    quvi_t q;
> +    quvi_media_t m;
> +    QUVIcode rc;
> +    LibQuviContext *qc = s->priv_data;
> +    char *media_url, *pagetitle;
> +
> +    rc = quvi_init(&q);
> +    if (rc != QUVI_OK)
> +        goto quvi_fail;
> +
> +    quvi_setopt(q, QUVIOPT_FORMAT, qc->format);
> +
> +    rc = quvi_parse(q, s->filename, &m);
> +    if (rc != QUVI_OK)
> +        goto quvi_fail;
> +
> +    rc = quvi_getprop(m, QUVIPROP_MEDIAURL, &media_url);
> +    if (rc != QUVI_OK)
> +        goto quvi_fail;
> +
> +    ret = avformat_open_input(&qc->fmtctx, media_url, NULL, NULL);
> +    if (ret < 0)
> +        goto end;
> +
> +    rc = quvi_getprop(m, QUVIPROP_PAGETITLE, &pagetitle);
> +    if (rc == QUVI_OK)
> +        av_dict_set(&s->metadata, "title", pagetitle, 0);
> +
> +    for (i = 0; i < qc->fmtctx->nb_streams; i++) {
> +        AVStream *st = avformat_new_stream(s, NULL);
> +        AVStream *ist = qc->fmtctx->streams[i];
> +        if (!st) {
> +            ret = AVERROR(ENOMEM);
> +            goto end;
> +        }
> +        avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
> +        avcodec_copy_context(st->codec, qc->fmtctx->streams[i]->codec);
> +    }
> +
> +    return 0;
> +
> +quvi_fail:
> +    av_log(s, AV_LOG_ERROR, "%s\n", quvi_strerror(&q, rc));

This could be expanded a bit:

"Error occurred when parsing URL '%s': %s\n"

> +    ret = rc;

is this a valid error code (shouldn't it be AVERROR_EXTERNAL or such)?

[...]
-- 
FFmpeg = Fancy and Fancy Maxi Political Epic Genius


More information about the ffmpeg-devel mailing list