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

wm4 nfxjfg at googlemail.com
Sun Jun 1 17:20:14 CEST 2014


On Sun, 1 Jun 2014 17:02:44 +0200
Carl Eugen Hoyos <cehoyos at ag.or.at> wrote:

> diff --git a/Changelog b/Changelog
> index 3d416c4..7e13c4d 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -26,6 +26,7 @@ version <next>:
>  - native Opus decoder
>  - display matrix export and rotation api
>  - WebVTT encoder
> +- Image format auto-detection
>  
>  
>  version 2.2:
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 7b7156c..87a6a79 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -185,6 +185,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 30e5d30..03a9264 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -149,6 +149,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..e0dfde4 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 / 2;
> +        }
> +    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 / 2;
> +    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}
> +};

Splitting this into multiple per-format demuxers would be cleaner. It
would for example allow the user (or application using the lavf) to
force a specific format, to get more control over probing (like black
listing problematic formats or whatever), and would generally fit the
libavformat architecture better.

To reduce the code size, you could do it like with the PCM codecs in
libavcodec.

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

I'm still confused why this checks only the prefix of the name.

>      }
>  
>      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;
> +
> +            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;
> +        }
> +        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
> @@ -387,6 +504,8 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
>              return AVERROR(EIO);
>          if (s->frame_size > 0) {
>              size[0] = s->frame_size;
> +        } else if (!strncmp(s1->iformat->name, "imageauto", 9)) {
> +            size[0] = avio_size(s1->pb);

Same here.

>          } else {
>              size[0] = 4096;
>          }
> @@ -522,3 +641,22 @@ AVInputFormat ff_image2pipe_demuxer = {
>      .priv_class     = &img2pipe_class,
>  };
>  #endif
> +#if CONFIG_IMAGEAUTO_DEMUXER
> +static const AVClass imgauto_class = {
> +    .class_name = "imageauto demuxer",
> +    .item_name  = av_default_item_name,
> +    .option     = options,
> +    .version    = LIBAVUTIL_VERSION_INT,
> +};
> +AVInputFormat ff_imageauto_demuxer = {
> +    .name           = "imageauto",
> +    .long_name      = NULL_IF_CONFIG_SMALL("single image auto-detection"),
> +    .priv_data_size = sizeof(VideoDemuxData),
> +    .read_probe     = imgauto_read_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     = &imgauto_class,
> +};
> +#endif
> diff --git a/libavformat/version.h b/libavformat/version.h
> index 6f7aa7d..e9cc16d 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 42
> +#define LIBAVFORMAT_VERSION_MINOR 43
>  #define LIBAVFORMAT_VERSION_MICRO 100
>  
>  #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \



More information about the ffmpeg-devel mailing list