[FFmpeg-devel] [PATCH] avformat: Add image3 demuxers with format autodetection

Michael Niedermayer michaelni at gmx.at
Thu Jul 3 19:42:23 CEST 2014


On Tue, Jul 01, 2014 at 02:22:54AM +0200, wm4 wrote:
> On Tue, 1 Jul 2014 00:27:42 +0200
> Michael Niedermayer <michaelni at gmx.at> wrote:
> 
> > On Mon, Jun 30, 2014 at 09:53:46PM +0200, wm4 wrote:
> > > On Mon, 30 Jun 2014 03:44:17 +0200
> > > Michael Niedermayer <michaelni at gmx.at> wrote:
> > > 
> > > > From: Carl Eugen Hoyos <cehoyos at ag.or.at>
> > > > 
> > > > Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> > > > ---
> > > >  Changelog                |    1 +
> > > >  libavformat/Makefile     |    8 +++
> > > >  libavformat/allformats.c |   11 ++++
> > > >  libavformat/img2dec.c    |  137 +++++++++++++++++++++++++++++++++++++++++++++-
> > > >  libavformat/version.h    |    2 +-
> > > >  5 files changed, 157 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/Changelog b/Changelog
> > > > index 0346877..3013c25 100644
> > > > --- a/Changelog
> > > > +++ b/Changelog
> > > > @@ -30,6 +30,7 @@ version <next>:
> > > >  - zoompan filter
> > > >  - signalstats filter
> > > >  - hqx filter (hq2x, hq3x, hq4x)
> > > > +- Image format auto-detection
> > > >  
> > > >  
> > > >  version 2.2:
> > > > diff --git a/libavformat/Makefile b/libavformat/Makefile
> > > > index 46aac96..857bfbb 100644
> > > > --- a/libavformat/Makefile
> > > > +++ b/libavformat/Makefile
> > > > @@ -187,6 +187,14 @@ OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER)        += img2dec.o img2.o
> > > >  OBJS-$(CONFIG_IMAGE2PIPE_MUXER)          += img2enc.o img2.o
> > > >  OBJS-$(CONFIG_IMAGE2_ALIAS_PIX_DEMUXER)  += img2_alias_pix.o
> > > >  OBJS-$(CONFIG_IMAGE2_BRENDER_PIX_DEMUXER) += img2_brender_pix.o
> > > > +OBJS-$(CONFIG_IMAGE_BMP_PIPE_DEMUXER)     += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_DPX_PIPE_DEMUXER)     += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_EXR_PIPE_DEMUXER)     += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER)  += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER)     += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_SGI_PIPE_DEMUXER)     += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_TIFF_PIPE_DEMUXER)    += img2dec.o img2.o
> > > >  OBJS-$(CONFIG_INGENIENT_DEMUXER)         += ingenientdec.o rawdec.o
> > > >  OBJS-$(CONFIG_IPMOVIE_DEMUXER)           += ipmovie.o
> > > >  OBJS-$(CONFIG_IRCAM_DEMUXER)             += ircamdec.o ircam.o pcm.o
> > > > diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> > > > index dc5557c..dbde432 100644
> > > > --- a/libavformat/allformats.c
> > > > +++ b/libavformat/allformats.c
> > > > @@ -318,6 +318,17 @@ void av_register_all(void)
> > > >      REGISTER_DEMUXER (YOP,              yop);
> > > >      REGISTER_MUXDEMUX(YUV4MPEGPIPE,     yuv4mpegpipe);
> > > >  
> > > > +    /* image demuxers */
> > > > +    REGISTER_DEMUXER (IMAGE_BMP_PIPE,        image_bmp_pipe);
> > > > +    REGISTER_DEMUXER (IMAGE_DPX_PIPE,        image_dpx_pipe);
> > > > +    REGISTER_DEMUXER (IMAGE_EXR_PIPE,        image_exr_pipe);
> > > > +    REGISTER_DEMUXER (IMAGE_PICTOR_PIPE,     image_pictor_pipe);
> > > > +    REGISTER_DEMUXER (IMAGE_PNG_PIPE,        image_png_pipe);
> > > > +    REGISTER_DEMUXER (IMAGE_SGI_PIPE,        image_sgi_pipe);
> > > > +    REGISTER_DEMUXER (IMAGE_SUNRAST_PIPE,    image_sunrast_pipe);
> > > > +    REGISTER_DEMUXER (IMAGE_TIFF_PIPE,       image_tiff_pipe);
> > > > +
> > > > +
> > > >      /* protocols */
> > > >      REGISTER_PROTOCOL(BLURAY,           bluray);
> > > >      REGISTER_PROTOCOL(CACHE,            cache);
> > > > diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
> > > > index dc962db..6fa6157 100644
> > > > --- a/libavformat/img2dec.c
> > > > +++ b/libavformat/img2dec.c
> > > > @@ -27,6 +27,7 @@
> > > >  #include "libavutil/opt.h"
> > > >  #include "libavutil/pixdesc.h"
> > > >  #include "libavutil/parseutils.h"
> > > > +#include "libavutil/intreadwrite.h"
> > > >  #include "avformat.h"
> > > >  #include "internal.h"
> > > >  #include "img2.h"
> > > > @@ -302,7 +303,34 @@ int ff_img_read_header(AVFormatContext *s1)
> > > >          const char *str = strrchr(s->path, '.');
> > > >          s->split_planes       = str && !av_strcasecmp(str + 1, "y");
> > > >          st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
> > > > -        st->codec->codec_id   = ff_guess_image2_codec(s->path);
> > > > +        if (s1->pb) {
> > > > +            struct image_probe *probe;
> > > > +            uint8_t probe_buffer[AVPROBE_PADDING_SIZE] = {0};
> > > > +            AVInputFormat *fmt = NULL;
> > > > +            AVProbeData pd;
> > > > +            int ret = avio_read(s1->pb, probe_buffer, 8);
> > > > +            if (ret < 8)
> > > > +                return AVERROR(EINVAL);
> > > > +            avio_seek(s1->pb, -8, SEEK_CUR);
> > > > +
> > > > +            pd.buf = probe_buffer;
> > > > +            pd.buf_size = 8;
> > > > +            pd.filename = s1->filename;
> > > > +
> > > > +            while ((fmt = av_iformat_next(fmt))) {
> > > > +                if (fmt->read_header != ff_img_read_header ||
> > > > +                    !fmt->read_probe ||
> > > > +                    (fmt->flags & AVFMT_NOFILE) ||
> > > > +                    !fmt->raw_codec_id)
> > > > +                    continue;
> > > > +                if (fmt->read_probe(&pd) > 0) {
> > > > +                    st->codec->codec_id = fmt->raw_codec_id;
> > > > +                    break;
> > > > +                }
> > > > +            }
> > > > +        }
> > > 
> > > I guess all this is needed only to avoid having a separate
> > > ff_img_read_header function for each format?
> > 
> > it also allows "-f image2pipe" to recognize the format as well as
> > allowing test.png.%dnoname
> > this would nt work oterwise as the probing code would try to open
> > test.png.%dnoname not finding such a file and neither finding an
> > extension to identify it thus would require manually specifying png
> > 
> > 
> > > 
> > > Also, I suppose reading and seeking back by 8 bytes always works, even
> > > if the underlying stream is not seekable, and there are no corner cases
> > > that could happen that would lead to the buffer being flushed when
> > > reading these 8 bytes?
> > 
> > the 8 byte reading originates from the original patch, iam not happy
> > about it either. It should be ok in practice but i certainly would
> > prefer if it could be done more generically and robust ...
> > but probably better to do this as a seperate patch if its done
> 
> In general, it would be nice if avio had some sort of peek() function,
> which reads some buffer, but guarantees that the buffer isn't lost. For
> now it might be ok in practice, I agree.
> 
> > 
> > > 
> > > > +        if (st->codec->codec_id == AV_CODEC_ID_NONE)
> > > > +            st->codec->codec_id = ff_guess_image2_codec(s->path);
> > > >          if (st->codec->codec_id == AV_CODEC_ID_LJPEG)
> > > >              st->codec->codec_id = AV_CODEC_ID_MJPEG;
> > > >          if (st->codec->codec_id == AV_CODEC_ID_ALIAS_PIX) // we cannot distingiush this from BRENDER_PIX
> > > > @@ -522,3 +550,110 @@ AVInputFormat ff_image2pipe_demuxer = {
> > > >      .priv_class     = &img2pipe_class,
> > > >  };
> > > >  #endif
> > > > +
> > > > +static int bmp_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RB16(b) == 0x424d)
> > > > +        if (!AV_RN32(p + 6)) {
> > > > +            return AVPROBE_SCORE_EXTENSION + 1;
> > > > +        } else {
> > > > +            return AVPROBE_SCORE_EXTENSION / 4;
> > > > +        }
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int dpx_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RN32(b) == AV_RN32("SDPX") || AV_RN32(b) == AV_RN32("XPDS"))
> > > > +        return AVPROBE_SCORE_EXTENSION + 1;
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int exr_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RL32(b) == 20000630)
> > > > +        return AVPROBE_SCORE_EXTENSION + 1;
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int pictor_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RL16(b) == 0x1234)
> > > > +        return AVPROBE_SCORE_EXTENSION / 4;
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int png_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RB64(b) == 0x89504e470d0a1a0a)
> > > > +        return AVPROBE_SCORE_MAX - 1;
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int sgi_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RB16(b) == 474 &&
> > > > +        (b[2] & ~1) == 0 &&
> > > > +        (b[3] & ~3) == 0 && b[3] &&
> > > > +        (AV_RB16(b + 4) & ~7) == 0 && AV_RB16(b + 4))
> > > > +        return AVPROBE_SCORE_EXTENSION + 1;
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int sunrast_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RB32(b) == 0x59a66a95)
> > > > +        return AVPROBE_SCORE_EXTENSION + 1;
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int tiff_probe(AVProbeData *p)
> > > > +{
> > > > +    const uint8_t *b = p->buf;
> > > > +
> > > > +    if (AV_RB32(b) == 0x49492a00)
> > > > +        return AVPROBE_SCORE_EXTENSION + 1;
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +#define IMAGEAUTO_DEMUXER(imgname, codecid)\
> > > > +static const AVClass imgname ## _class = {\
> > > > +    .class_name = AV_STRINGIFY(imgname) " demuxer",\
> > > > +    .item_name  = av_default_item_name,\
> > > > +    .option     = options,\
> > > > +    .version    = LIBAVUTIL_VERSION_INT,\
> > > > +};\
> > > > +AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\
> > > > +    .name           = AV_STRINGIFY(imgname) "_pipe",\
> > > > +    .priv_data_size = sizeof(VideoDemuxData),\
> > > > +    .read_probe     = imgname ## _probe,\
> > > > +    .read_header    = ff_img_read_header,\
> > > > +    .read_packet    = ff_img_read_packet,\
> > > > +    .read_close     = img_read_close,\
> > > > +    .read_seek      = img_read_seek,\
> > > > +    .priv_class     = & imgname ## _class,\
> > > > +    .raw_codec_id   = codecid,\
> > > > +};
> > > > +
> > > > +IMAGEAUTO_DEMUXER(bmp,     AV_CODEC_ID_BMP)
> > > > +IMAGEAUTO_DEMUXER(dpx,     AV_CODEC_ID_DPX)
> > > > +IMAGEAUTO_DEMUXER(exr,     AV_CODEC_ID_EXR)
> > > > +IMAGEAUTO_DEMUXER(pictor,  AV_CODEC_ID_PICTOR)
> > > > +IMAGEAUTO_DEMUXER(png,     AV_CODEC_ID_PNG)
> > > > +IMAGEAUTO_DEMUXER(sgi,     AV_CODEC_ID_SGI)
> > > > +IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST)
> > > > +IMAGEAUTO_DEMUXER(tiff,    AV_CODEC_ID_TIFF)
> > > > diff --git a/libavformat/version.h b/libavformat/version.h
> > > > index 67393e0..a5b24bf 100644
> > > > --- a/libavformat/version.h
> > > > +++ b/libavformat/version.h
> > > > @@ -30,7 +30,7 @@
> > > >  #include "libavutil/version.h"
> > > >  
> > > >  #define LIBAVFORMAT_VERSION_MAJOR 55
> > > > -#define LIBAVFORMAT_VERSION_MINOR 44
> > > > +#define LIBAVFORMAT_VERSION_MINOR 45
> > > >  #define LIBAVFORMAT_VERSION_MICRO 100
> > > >  
> > > >  #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
> > > 
> > > Looks good to me. IMO better than other hacks, and looks clean at least
> > > from the outside.
> > 
> > there still one apsect i like to point at so its not missed, the
> > new formats are called bmp_pipe, dpx_pipe, ...
> > this matches the image2 / image2pipe terminology except the "_"
> > we could add non pipe variants but they would not be autoselected
> > by the current probe system as it wouldnt scan and open a file with
> > wildcards / %d in it
> 
> IMO the wildcard thing is a bit odd and should be in its own
> pseudo-demuxer, while normal image formats like "bmp" should exist and
> work like everything else in libavformat.
> 
> Would it be hard to add these formats? Wouldn't it just require
> extending the macro above a little?

should be easy, ill look into it unless i forget / someone else is
quicker


> 
> > 
> > If there are no objections / further comments then ill push this
> > tomorrow
> 
> No objections from me...

applied

thanks

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Those who are too smart to engage in politics are punished by being
governed by those who are dumber. -- Plato 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140703/f59030c8/attachment.asc>


More information about the ffmpeg-devel mailing list