[FFmpeg-devel] [PATCH] avformat: Add image3 demuxers with format autodetection
Michael Niedermayer
michaelni at gmx.at
Thu Jul 3 19:42:23 CEST 2014
On Tue, Jul 01, 2014 at 02:22:54AM +0200, wm4 wrote:
> On Tue, 1 Jul 2014 00:27:42 +0200
> Michael Niedermayer <michaelni at gmx.at> wrote:
>
> > On Mon, Jun 30, 2014 at 09:53:46PM +0200, wm4 wrote:
> > > On Mon, 30 Jun 2014 03:44:17 +0200
> > > Michael Niedermayer <michaelni at gmx.at> wrote:
> > >
> > > > From: Carl Eugen Hoyos <cehoyos at ag.or.at>
> > > >
> > > > Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> > > > ---
> > > > Changelog | 1 +
> > > > libavformat/Makefile | 8 +++
> > > > libavformat/allformats.c | 11 ++++
> > > > libavformat/img2dec.c | 137 +++++++++++++++++++++++++++++++++++++++++++++-
> > > > libavformat/version.h | 2 +-
> > > > 5 files changed, 157 insertions(+), 2 deletions(-)
> > > >
> > > > 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 46aac96..857bfbb 100644
> > > > --- a/libavformat/Makefile
> > > > +++ b/libavformat/Makefile
> > > > @@ -187,6 +187,14 @@ 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_IMAGE_BMP_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_DPX_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_EXR_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_SGI_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER) += img2dec.o img2.o
> > > > +OBJS-$(CONFIG_IMAGE_TIFF_PIPE_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..dbde432 100644
> > > > --- a/libavformat/allformats.c
> > > > +++ b/libavformat/allformats.c
> > > > @@ -318,6 +318,17 @@ void av_register_all(void)
> > > > REGISTER_DEMUXER (YOP, yop);
> > > > REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe);
> > > >
> > > > + /* image demuxers */
> > > > + REGISTER_DEMUXER (IMAGE_BMP_PIPE, image_bmp_pipe);
> > > > + REGISTER_DEMUXER (IMAGE_DPX_PIPE, image_dpx_pipe);
> > > > + REGISTER_DEMUXER (IMAGE_EXR_PIPE, image_exr_pipe);
> > > > + REGISTER_DEMUXER (IMAGE_PICTOR_PIPE, image_pictor_pipe);
> > > > + REGISTER_DEMUXER (IMAGE_PNG_PIPE, image_png_pipe);
> > > > + REGISTER_DEMUXER (IMAGE_SGI_PIPE, image_sgi_pipe);
> > > > + REGISTER_DEMUXER (IMAGE_SUNRAST_PIPE, image_sunrast_pipe);
> > > > + REGISTER_DEMUXER (IMAGE_TIFF_PIPE, image_tiff_pipe);
> > > > +
> > > > +
> > > > /* protocols */
> > > > REGISTER_PROTOCOL(BLURAY, bluray);
> > > > REGISTER_PROTOCOL(CACHE, cache);
> > > > diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
> > > > index dc962db..6fa6157 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"
> > > > @@ -302,7 +303,34 @@ 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};
> > > > + AVInputFormat *fmt = NULL;
> > > > + AVProbeData pd;
> > > > + int ret = avio_read(s1->pb, probe_buffer, 8);
> > > > + if (ret < 8)
> > > > + return AVERROR(EINVAL);
> > > > + avio_seek(s1->pb, -8, SEEK_CUR);
> > > > +
> > > > + pd.buf = probe_buffer;
> > > > + pd.buf_size = 8;
> > > > + pd.filename = s1->filename;
> > > > +
> > > > + while ((fmt = av_iformat_next(fmt))) {
> > > > + if (fmt->read_header != ff_img_read_header ||
> > > > + !fmt->read_probe ||
> > > > + (fmt->flags & AVFMT_NOFILE) ||
> > > > + !fmt->raw_codec_id)
> > > > + continue;
> > > > + if (fmt->read_probe(&pd) > 0) {
> > > > + st->codec->codec_id = fmt->raw_codec_id;
> > > > + break;
> > > > + }
> > > > + }
> > > > + }
> > >
> > > I guess all this is needed only to avoid having a separate
> > > ff_img_read_header function for each format?
> >
> > it also allows "-f image2pipe" to recognize the format as well as
> > allowing test.png.%dnoname
> > this would nt work oterwise as the probing code would try to open
> > test.png.%dnoname not finding such a file and neither finding an
> > extension to identify it thus would require manually specifying png
> >
> >
> > >
> > > Also, I suppose reading and seeking back by 8 bytes always works, even
> > > if the underlying stream is not seekable, and there are no corner cases
> > > that could happen that would lead to the buffer being flushed when
> > > reading these 8 bytes?
> >
> > the 8 byte reading originates from the original patch, iam not happy
> > about it either. It should be ok in practice but i certainly would
> > prefer if it could be done more generically and robust ...
> > but probably better to do this as a seperate patch if its done
>
> In general, it would be nice if avio had some sort of peek() function,
> which reads some buffer, but guarantees that the buffer isn't lost. For
> now it might be ok in practice, I agree.
>
> >
> > >
> > > > + 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
> > > > @@ -522,3 +550,110 @@ AVInputFormat ff_image2pipe_demuxer = {
> > > > .priv_class = &img2pipe_class,
> > > > };
> > > > #endif
> > > > +
> > > > +static int bmp_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RB16(b) == 0x424d)
> > > > + if (!AV_RN32(p + 6)) {
> > > > + return AVPROBE_SCORE_EXTENSION + 1;
> > > > + } else {
> > > > + return AVPROBE_SCORE_EXTENSION / 4;
> > > > + }
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int dpx_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RN32(b) == AV_RN32("SDPX") || AV_RN32(b) == AV_RN32("XPDS"))
> > > > + return AVPROBE_SCORE_EXTENSION + 1;
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int exr_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RL32(b) == 20000630)
> > > > + return AVPROBE_SCORE_EXTENSION + 1;
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int pictor_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RL16(b) == 0x1234)
> > > > + return AVPROBE_SCORE_EXTENSION / 4;
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int png_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RB64(b) == 0x89504e470d0a1a0a)
> > > > + return AVPROBE_SCORE_MAX - 1;
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int sgi_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RB16(b) == 474 &&
> > > > + (b[2] & ~1) == 0 &&
> > > > + (b[3] & ~3) == 0 && b[3] &&
> > > > + (AV_RB16(b + 4) & ~7) == 0 && AV_RB16(b + 4))
> > > > + return AVPROBE_SCORE_EXTENSION + 1;
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int sunrast_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RB32(b) == 0x59a66a95)
> > > > + return AVPROBE_SCORE_EXTENSION + 1;
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int tiff_probe(AVProbeData *p)
> > > > +{
> > > > + const uint8_t *b = p->buf;
> > > > +
> > > > + if (AV_RB32(b) == 0x49492a00)
> > > > + return AVPROBE_SCORE_EXTENSION + 1;
> > > > + return 0;
> > > > +}
> > > > +
> > > > +#define IMAGEAUTO_DEMUXER(imgname, codecid)\
> > > > +static const AVClass imgname ## _class = {\
> > > > + .class_name = AV_STRINGIFY(imgname) " demuxer",\
> > > > + .item_name = av_default_item_name,\
> > > > + .option = options,\
> > > > + .version = LIBAVUTIL_VERSION_INT,\
> > > > +};\
> > > > +AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\
> > > > + .name = AV_STRINGIFY(imgname) "_pipe",\
> > > > + .priv_data_size = sizeof(VideoDemuxData),\
> > > > + .read_probe = imgname ## _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 = & imgname ## _class,\
> > > > + .raw_codec_id = codecid,\
> > > > +};
> > > > +
> > > > +IMAGEAUTO_DEMUXER(bmp, AV_CODEC_ID_BMP)
> > > > +IMAGEAUTO_DEMUXER(dpx, AV_CODEC_ID_DPX)
> > > > +IMAGEAUTO_DEMUXER(exr, AV_CODEC_ID_EXR)
> > > > +IMAGEAUTO_DEMUXER(pictor, AV_CODEC_ID_PICTOR)
> > > > +IMAGEAUTO_DEMUXER(png, AV_CODEC_ID_PNG)
> > > > +IMAGEAUTO_DEMUXER(sgi, AV_CODEC_ID_SGI)
> > > > +IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST)
> > > > +IMAGEAUTO_DEMUXER(tiff, AV_CODEC_ID_TIFF)
> > > > 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, \
> > >
> > > Looks good to me. IMO better than other hacks, and looks clean at least
> > > from the outside.
> >
> > there still one apsect i like to point at so its not missed, the
> > new formats are called bmp_pipe, dpx_pipe, ...
> > this matches the image2 / image2pipe terminology except the "_"
> > we could add non pipe variants but they would not be autoselected
> > by the current probe system as it wouldnt scan and open a file with
> > wildcards / %d in it
>
> IMO the wildcard thing is a bit odd and should be in its own
> pseudo-demuxer, while normal image formats like "bmp" should exist and
> work like everything else in libavformat.
>
> Would it be hard to add these formats? Wouldn't it just require
> extending the macro above a little?
should be easy, ill look into it unless i forget / someone else is
quicker
>
> >
> > If there are no objections / further comments then ill push this
> > tomorrow
>
> No objections from me...
applied
thanks
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Those who are too smart to engage in politics are punished by being
governed by those who are dumber. -- Plato
-------------- 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/20140703/f59030c8/attachment.asc>
More information about the ffmpeg-devel
mailing list