[FFmpeg-devel] [PATCH]Add an image3 demuxer with format autodetection

Michael Niedermayer michaelni at gmx.at
Tue Jun 24 17:04:16 CEST 2014


On Sat, Jun 21, 2014 at 09:43:19PM +0200, Carl Eugen Hoyos wrote:
> On Sunday 01 June 2014 05:02:44 pm Carl Eugen Hoyos wrote:
> > On Sunday 01 June 2014 03:55:46 pm Nicolas George wrote:
> > > Le primidi 11 prairial, an CCXXII, Carl Eugen Hoyos a écrit :
> > > > +OBJS-$(CONFIG_IMAGE3_DEMUXER)            += img2dec.o img2.o
> > >
> > > The whole idea looks like a good idea, just a small nit: maybe a more
> > > explicit name would be better than just a number. Maybe "imageauto"
> >
> > Changed to imageauto (which I prefer over image2auto).
> 
> Updated patch attached.
> 
> Please review, Carl Eugen

>  Changelog                |    1 
>  libavformat/Makefile     |    1 
>  libavformat/allformats.c |    1 
>  libavformat/img2dec.c    |  142 ++++++++++++++++++++++++++++++++++++++++++++++-
>  libavformat/version.h    |    2 
>  5 files changed, 144 insertions(+), 3 deletions(-)
> 7e7e5c3f99f46ae45e4fa29431902320b08bc7f3  patchprobe3.diff
> 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 ecae4d0..1e43209 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -187,6 +187,7 @@ 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_IMAGEAUTO_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..5115948 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -150,6 +150,7 @@ void av_register_all(void)
>      REGISTER_MUXDEMUX(IMAGE2PIPE,       image2pipe);
>      REGISTER_DEMUXER (IMAGE2_ALIAS_PIX, image2_alias_pix);
>      REGISTER_DEMUXER (IMAGE2_BRENDER_PIX, image2_brender_pix);
> +    REGISTER_DEMUXER (IMAGEAUTO,        imageauto);
>      REGISTER_DEMUXER (INGENIENT,        ingenient);
>      REGISTER_DEMUXER (IPMOVIE,          ipmovie);
>      REGISTER_MUXER   (IPOD,             ipod);
> diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
> index dc962db..fe0798f 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"
> @@ -153,6 +154,107 @@ fail:
>      return -1;
>  }
>  
> +static int bmp_probe(uint8_t *p)
> +{
> +    if (AV_RB16(p) == 0x424d)
> +        if (!AV_RN32(p + 6)) {
> +            return AVPROBE_SCORE_EXTENSION + 1;
> +        } else {
> +            return AVPROBE_SCORE_EXTENSION / 4;
> +        }
> +    return 0;
> +}
> +
> +static int dpx_probe(uint8_t *p)
> +{
> +    if (AV_RN32(p) == AV_RN32("SDPX") || AV_RN32(p) == AV_RN32("XPDS"))
> +        return AVPROBE_SCORE_EXTENSION + 1;
> +    return 0;
> +}
> +
> +static int exr_probe(uint8_t *p)
> +{
> +    if (AV_RL32(p) == 20000630)
> +        return AVPROBE_SCORE_EXTENSION + 1;
> +    return 0;
> +}
> +
> +static int jpegls_probe(uint8_t *p)
> +{
> +    if (AV_RB32(p) == 0xffd8fff7)
> +        return AVPROBE_SCORE_EXTENSION + 1;
> +    return 0;
> +}
> +
> +static int pictor_probe(uint8_t *p)
> +{
> +    if (AV_RL16(p) == 0x1234)
> +        return AVPROBE_SCORE_EXTENSION / 4;
> +    return 0;
> +}
> +
> +static int png_probe(uint8_t *p)
> +{
> +    if (AV_RB64(p) == 0x89504e470d0a1a0a)
> +        return AVPROBE_SCORE_MAX - 1;
> +    return 0;
> +}
> +
> +static int sgi_probe(uint8_t *p)
> +{
> +    if (AV_RB16(p) == 474 &&
> +        (p[2] & ~1) == 0 &&
> +        (p[3] & ~3) == 0 && p[3] &&
> +        (AV_RB16(p + 4) & ~7) == 0 && AV_RB16(p + 4))
> +        return AVPROBE_SCORE_EXTENSION + 1;
> +    return 0;
> +}
> +
> +static int sunrast_probe(uint8_t *p)
> +{
> +    if (AV_RB32(p) == 0x59a66a95)
> +        return AVPROBE_SCORE_EXTENSION + 1;
> +    return 0;
> +}
> +
> +static int tiff_probe(uint8_t *p)
> +{
> +    if (AV_RB32(p) == 0x49492a00)
> +        return AVPROBE_SCORE_EXTENSION + 1;
> +    return 0;
> +}
> +
> +struct image_probe {
> +    int (*f)(uint8_t *p);
> +    enum AVCodecID codec_id;
> +};
> +
> +static struct image_probe probe_functions[] = {
> +    { bmp_probe,     AV_CODEC_ID_BMP },
> +    { dpx_probe,     AV_CODEC_ID_DPX },
> +    { exr_probe,     AV_CODEC_ID_EXR },
> +    { jpegls_probe,  AV_CODEC_ID_JPEGLS},
> +    { pictor_probe,  AV_CODEC_ID_PICTOR },
> +    { png_probe,     AV_CODEC_ID_PNG },
> +    { sgi_probe,     AV_CODEC_ID_SGI },
> +    { sunrast_probe, AV_CODEC_ID_SUNRAST },
> +    { tiff_probe,    AV_CODEC_ID_TIFF },
> +    { NULL, 0}
> +};
> +
> +static int imgauto_read_probe(AVProbeData *p)
> +{
> +    struct image_probe *probe;
> +
> +    for (probe = probe_functions; probe->f; probe++) {
> +        int ret;
> +        ret = probe->f(p->buf);
> +        if (ret > 0)
> +            return ret;
> +    }
> +    return 0;
> +}

I support the suggestion from wm4 (and i belive nicolas) of
1 AVInputFormat per AV_CODEC

it shouldnt change much in the implementation i think, just a few
more structs


> +
>  static int img_read_probe(AVProbeData *p)
>  {
>      if (p->filename && ff_guess_image2_codec(p->filename)) {
> @@ -198,7 +300,8 @@ int ff_img_read_header(AVFormatContext *s1)
>          s->is_pipe = 0;
>      else {
>          s->is_pipe       = 1;
> -        st->need_parsing = AVSTREAM_PARSE_FULL;
> +        if (strncmp(s1->iformat->name, "imageauto", 9))
> +            st->need_parsing = AVSTREAM_PARSE_FULL;
>      }
>  
>      if (s->ts_from_file == 2) {
> @@ -302,7 +405,21 @@ 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};
> +            int ret = avio_read(s1->pb, probe_buffer, 8);
> +            if (ret < 8)
> +                return AVERROR(EINVAL);
> +            avio_seek(s1->pb, -8, SEEK_CUR);
> +            for (probe = probe_functions; probe->f; probe++)
> +                if (probe->f(probe_buffer)) {
> +                    st->codec->codec_id = probe->codec_id;
> +                    break;
> +                }
> +        }

this codec detection also would become more robust with a format
per codec.
As is it has only 8 bytes for probing and increasing that
complicates things as there then could be the need to stepwise
increase until detection and reuse of the read data to avoid seekback
on unseekable input

besides this the code looks nice and clean, i like the implementation

Thanks

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No human being will ever know the Truth, for even if they happen to say it
by chance, they would not even known they had done so. -- Xenophanes
-------------- 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/20140624/2c33858c/attachment.asc>


More information about the ffmpeg-devel mailing list