[FFmpeg-devel] [PATCH] avformat: Add image3 demuxers with format autodetection
Michael Niedermayer
michaelni at gmx.at
Tue Jul 1 00:27:42 CEST 2014
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
>
> > + 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
If there are no objections / further comments then ill push this
tomorrow
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
What does censorship reveal? It reveals fear. -- Julian Assange
-------------- 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/20140701/c2651ca4/attachment.asc>
More information about the ffmpeg-devel
mailing list