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

Carl Eugen Hoyos cehoyos at ag.or.at
Sat Jun 21 21:43:19 CEST 2014


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
-------------- next part --------------
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;
+}
+
 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;
+                }
+        }
+        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);
         } 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 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, \


More information about the ffmpeg-devel mailing list