[FFmpeg-devel] [WIP]Image format auto-detection

Carl Eugen Hoyos cehoyos at ag.or.at
Thu May 29 01:56:29 CEST 2014


Hi!

Attached is a patch that allows image format auto-detection for formats that 
have an appropriate header.
It does not work correctly because parsing should be disabled for bmp etc. 
since some parsers are more strict than the corresponding decoder (see for 
example ticket #3402) but the commented-out line breaks fate.

Atm, I think a new demuxer image3 that is only useful for auto-detection is a 
solution, any other suggestions?

Thank you, Carl Eugen
-------------- next part --------------
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
index dc962db..e7d7769 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,92 @@ fail:
     return -1;
 }
 
+static int bmp_probe(uint8_t *p)
+{
+    if (AV_RB16(p) == 0x424d)
+        return AVPROBE_SCORE_EXTENSION;
+    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_MAX / 2;
+    return 0;
+}
+
+static int exr_probe(uint8_t *p)
+{
+    if (AV_RL32(p) == 20000630)
+        return AVPROBE_SCORE_MAX / 2;
+    return 0;
+}
+
+static int pictor_probe(uint8_t *p)
+{
+    if (AV_RL16(p) == 0x1234)
+        return AVPROBE_SCORE_EXTENSION;
+    return 0;
+}
+
+static int png_probe(uint8_t *p)
+{
+    if (AV_RB64(p) == 0x89504e470d0a1a0a)
+        return AVPROBE_SCORE_MAX;
+    return 0;
+}
+
+static int sgi_probe(uint8_t *p)
+{
+    if(AV_RB16(p) == 474)
+        return AVPROBE_SCORE_EXTENSION;
+    return 0;
+}
+
+static int sunrast_probe(uint8_t *p)
+{
+    if (AV_RB32(p) == 0x59a66a95)
+        return AVPROBE_SCORE_MAX / 2;
+    return 0;
+}
+
+static int tiff_probe(uint8_t *p)
+{
+    if (AV_RB32(p) == 0x49492a00)
+        return AVPROBE_SCORE_MAX / 2;
+    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 },
+    { 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 image2pipe_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,6 +285,7 @@ int ff_img_read_header(AVFormatContext *s1)
         s->is_pipe = 0;
     else {
         s->is_pipe       = 1;
+//        if (avio_size(s1->pb) <= 0)
         st->need_parsing = AVSTREAM_PARSE_FULL;
     }
 
@@ -302,6 +390,20 @@ 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;
+        if (s1->pb) {
+            struct image_probe *probe;
+            uint8_t probe_buffer[8];
+            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;
@@ -387,6 +489,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 (avio_size(s1->pb) > 0) {
+            size[0] = avio_size(s1->pb);
         } else {
             size[0] = 4096;
         }
@@ -517,6 +621,7 @@ AVInputFormat ff_image2pipe_demuxer = {
     .name           = "image2pipe",
     .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
     .priv_data_size = sizeof(VideoDemuxData),
+    .read_probe     = image2pipe_read_probe,
     .read_header    = ff_img_read_header,
     .read_packet    = ff_img_read_packet,
     .priv_class     = &img2pipe_class,


More information about the ffmpeg-devel mailing list