[FFmpeg-devel] [PATCH]Add an image3 demuxer with format autodetection
Carl Eugen Hoyos
cehoyos at ag.or.at
Fri May 30 06:03:38 CEST 2014
On Thursday 29 May 2014 02:21:51 pm wm4 wrote:
> OK, but why stuff it all into one "super"-demuxer?
What advantage would another solution have?
(Apart from not supporting auto-detection for image2pipe.)
> > + if (memcmp(s1->iformat->name, "image3", 6))
> > + st->need_parsing = AVSTREAM_PARSE_FULL;
>
> Why not strcmp or at least strncmp?
Should be fixed, thank you!
> > + } else if (!memcmp(s1->iformat->name, "image3", 6)) {
> > + size[0] = avio_size(s1->pb);
>
> Again...
> Also, is it right to pass the whole file as packet,
> instead of trying to parse and sanitize the size of
> the data somehow?
How would that work for formats without a parser?
(Apart from "copied from image2".)
New patch attached.
Thank you, Carl Eugen
-------------- next part --------------
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 fdd0123..5534979 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_IMAGE3_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..bb3f499 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 (IMAGE3, image3);
REGISTER_DEMUXER (INGENIENT, ingenient);
REGISTER_DEMUXER (IPMOVIE, ipmovie);
REGISTER_MUXER (IPOD, ipod);
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
index dc962db..0479e2e 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}
+};
+
+static int img3_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, "image3", 6))
+ 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;
+
+ 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, "image3", 6)) {
+ 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_IMAGE3_DEMUXER
+static const AVClass img3_class = {
+ .class_name = "image3 demuxer",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+AVInputFormat ff_image3_demuxer = {
+ .name = "image3",
+ .long_name = NULL_IF_CONFIG_SMALL("single image"),
+ .priv_data_size = sizeof(VideoDemuxData),
+ .read_probe = img3_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 = &img3_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