[FFmpeg-cvslog] Microsoft Windows ICO demuxer
Peter Ross
git at videolan.org
Sun Dec 4 16:58:09 CET 2011
ffmpeg | branch: master | Peter Ross <pross at xvid.org> | Sun Dec 4 17:45:24 2011 +1100| [ba8410cb446cae58d1fa1d9e3891a67db92d4e14] | committer: Michael Niedermayer
Microsoft Windows ICO demuxer
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=ba8410cb446cae58d1fa1d9e3891a67db92d4e14
---
Changelog | 1 +
doc/general.texi | 2 +
libavformat/Makefile | 1 +
libavformat/allformats.c | 1 +
libavformat/icodec.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 171 insertions(+), 0 deletions(-)
diff --git a/Changelog b/Changelog
index 3b12e2a..1aa814e 100644
--- a/Changelog
+++ b/Changelog
@@ -127,6 +127,7 @@ easier to use. The changes are:
- ass filter
- CRI ADX audio format demuxer
- Playstation Portable PMP format demuxer
+- Microsoft Windows ICO demuxer
version 0.8:
diff --git a/doc/general.texi b/doc/general.texi
index 04ca71d..1b720f5 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -125,6 +125,8 @@ library:
@tab General eXchange Format SMPTE 360M, used by Thomson Grass Valley
playout servers.
@item iCEDraw File @tab @tab X
+ at item ICO @tab @tab X
+ @tab Microsoft Windows ICO
@item id Quake II CIN video @tab @tab X
@item id RoQ @tab X @tab X
@tab Used in Quake III, Jedi Knight 2 and other computer games.
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 1e59a91..4e3a183 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -111,6 +111,7 @@ OBJS-$(CONFIG_H263_DEMUXER) += h263dec.o rawdec.o
OBJS-$(CONFIG_H263_MUXER) += rawenc.o
OBJS-$(CONFIG_H264_DEMUXER) += h264dec.o rawdec.o
OBJS-$(CONFIG_H264_MUXER) += rawenc.o
+OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o
OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o
OBJS-$(CONFIG_IDF_DEMUXER) += bintext.o
OBJS-$(CONFIG_IFF_DEMUXER) += iff.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 9ba459d..9593bd5 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -110,6 +110,7 @@ void av_register_all(void)
REGISTER_MUXDEMUX (H261, h261);
REGISTER_MUXDEMUX (H263, h263);
REGISTER_MUXDEMUX (H264, h264);
+ REGISTER_DEMUXER (ICO, ico);
REGISTER_DEMUXER (IDCIN, idcin);
REGISTER_DEMUXER (IDF, idf);
REGISTER_DEMUXER (IFF, iff);
diff --git a/libavformat/icodec.c b/libavformat/icodec.c
new file mode 100644
index 0000000..e539b02
--- /dev/null
+++ b/libavformat/icodec.c
@@ -0,0 +1,166 @@
+/*
+ * Microsoft Windows ICO demuxer
+ * Copyright (c) 2011 Peter Ross (pross at xvid.org)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Microsoft Windows ICO demuxer
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "libavcodec/bytestream.h"
+#include "libavcodec/bmp.h"
+#include "avformat.h"
+#include "internal.h"
+
+typedef struct {
+ int offset;
+ int size;
+ int nb_pal;
+} IcoImage;
+
+typedef struct {
+ int current_image;
+ int nb_images;
+ IcoImage * images;
+} IcoDemuxContext;
+
+static int probe(AVProbeData *p)
+{
+ if (AV_RL16(p->buf) == 0 && AV_RL16(p->buf + 2) == 1 && AV_RL16(p->buf + 4))
+ return AVPROBE_SCORE_MAX / 3;
+ return 0;
+}
+
+static int read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ IcoDemuxContext *ico = s->priv_data;
+ AVIOContext *pb = s->pb;
+ int i;
+
+ avio_skip(pb, 4);
+ ico->nb_images = avio_rl16(pb);
+
+ ico->images = av_malloc(ico->nb_images * sizeof(IcoImage));
+ if (!ico->images)
+ return AVERROR(ENOMEM);
+
+ for (i = 0; i < ico->nb_images; i++) {
+ AVStream *st;
+
+ if (avio_seek(pb, 6 + i * 16, SEEK_SET) < 0)
+ break;
+
+ st = avformat_new_stream(s, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->width = avio_r8(pb);
+ st->codec->height = avio_r8(pb);
+ ico->images[i].nb_pal = avio_r8(pb);
+
+ avio_skip(pb, 3);
+ st->codec->bits_per_coded_sample = avio_rl16(pb);
+ if (st->codec->bits_per_coded_sample <= 8 && !ico->images[i].nb_pal)
+ ico->images[i].nb_pal = 1 << st->codec->bits_per_coded_sample;
+
+ ico->images[i].size = avio_rl32(pb);
+ ico->images[i].offset = avio_rl32(pb);
+
+ if (avio_seek(pb, ico->images[i].offset, SEEK_SET) < 0)
+ break;
+
+ switch(avio_rl32(pb)) {
+ case MKTAG(0x89, 'P', 'N', 'G'):
+ st->codec->codec_id = CODEC_ID_PNG;
+ st->codec->width = 0;
+ st->codec->height = 0;
+ break;
+ case 40:
+ st->codec->codec_id = CODEC_ID_BMP;
+ if (!st->codec->width || !st->codec->height) {
+ st->codec->width = avio_rl32(pb);
+ st->codec->height = avio_rl32(pb) / 2;
+ }
+ break;
+ default:
+ av_log_ask_for_sample(s, "unsupported codec\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ return 0;
+}
+
+static int read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ IcoDemuxContext *ico = s->priv_data;
+ IcoImage *image;
+ AVIOContext *pb = s->pb;
+ int ret;
+
+ if (ico->current_image >= ico->nb_images)
+ return AVERROR(EIO);
+
+ image = &ico->images[ico->current_image];
+
+ if ((ret = avio_seek(pb, image->offset, SEEK_SET)) < 0)
+ return ret;
+
+ if (s->streams[ico->current_image]->codec->codec_id == CODEC_ID_PNG) {
+ if ((ret = av_get_packet(pb, pkt, image->size)) < 0)
+ return ret;
+ } else {
+ uint8_t *buf;
+ if ((ret = av_new_packet(pkt, 14 + image->size)) < 0)
+ return ret;
+ buf = pkt->data;
+
+ /* add BMP header */
+ bytestream_put_byte(&buf, 'B');
+ bytestream_put_byte(&buf, 'M');
+ bytestream_put_le32(&buf, pkt->size);
+ bytestream_put_le16(&buf, 0);
+ bytestream_put_le16(&buf, 0);
+ bytestream_put_le32(&buf, 14 + 40 + image->nb_pal * 4);
+
+ if ((ret = avio_read(pb, buf, image->size)) < 0)
+ return ret;
+
+ AV_WL32(buf + 8, AV_RL32(buf + 8) / 2);
+ AV_WL32(buf + 32, image->nb_pal);
+ }
+
+ pkt->stream_index = ico->current_image++;
+ pkt->flags |= AV_PKT_FLAG_KEY;
+
+ return 0;
+}
+
+AVInputFormat ff_ico_demuxer = {
+ .name = "ico",
+ .long_name = NULL_IF_CONFIG_SMALL("Microsoft Windows ICO"),
+ .priv_data_size = sizeof(IcoDemuxContext),
+ .read_probe = probe,
+ .read_header = read_header,
+ .read_packet = read_packet,
+ .flags = AVFMT_NOTIMESTAMPS,
+};
More information about the ffmpeg-cvslog
mailing list