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

Michael Niedermayer michaelni at gmx.at
Tue Jul 1 00:27:42 CEST 2014


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


> 
> > +        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

If there are no objections / further comments then ill push this
tomorrow

[...]


-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

What does censorship reveal? It reveals fear. -- Julian Assange
-------------- 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/20140701/c2651ca4/attachment.asc>


More information about the ffmpeg-devel mailing list