Browse code

Microsoft Windows ICO demuxer

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Peter Ross authored on 2011/12/04 15:45:24
Showing 5 changed files
... ...
@@ -127,6 +127,7 @@ easier to use. The changes are:
127 127
 - ass filter
128 128
 - CRI ADX audio format demuxer
129 129
 - Playstation Portable PMP format demuxer
130
+- Microsoft Windows ICO demuxer
130 131
 
131 132
 
132 133
 version 0.8:
... ...
@@ -125,6 +125,8 @@ library:
125 125
     @tab General eXchange Format SMPTE 360M, used by Thomson Grass Valley
126 126
          playout servers.
127 127
 @item iCEDraw File              @tab   @tab X
128
+@item ICO                       @tab   @tab X
129
+    @tab Microsoft Windows ICO
128 130
 @item id Quake II CIN video     @tab   @tab X
129 131
 @item id RoQ                    @tab X @tab X
130 132
     @tab Used in Quake III, Jedi Knight 2 and other computer games.
... ...
@@ -111,6 +111,7 @@ OBJS-$(CONFIG_H263_DEMUXER)              += h263dec.o rawdec.o
111 111
 OBJS-$(CONFIG_H263_MUXER)                += rawenc.o
112 112
 OBJS-$(CONFIG_H264_DEMUXER)              += h264dec.o rawdec.o
113 113
 OBJS-$(CONFIG_H264_MUXER)                += rawenc.o
114
+OBJS-$(CONFIG_ICO_DEMUXER)               += icodec.o
114 115
 OBJS-$(CONFIG_IDCIN_DEMUXER)             += idcin.o
115 116
 OBJS-$(CONFIG_IDF_DEMUXER)               += bintext.o
116 117
 OBJS-$(CONFIG_IFF_DEMUXER)               += iff.o
... ...
@@ -110,6 +110,7 @@ void av_register_all(void)
110 110
     REGISTER_MUXDEMUX (H261, h261);
111 111
     REGISTER_MUXDEMUX (H263, h263);
112 112
     REGISTER_MUXDEMUX (H264, h264);
113
+    REGISTER_DEMUXER  (ICO, ico);
113 114
     REGISTER_DEMUXER  (IDCIN, idcin);
114 115
     REGISTER_DEMUXER  (IDF, idf);
115 116
     REGISTER_DEMUXER  (IFF, iff);
116 117
new file mode 100644
... ...
@@ -0,0 +1,166 @@
0
+/*
1
+ * Microsoft Windows ICO demuxer
2
+ * Copyright (c) 2011 Peter Ross (pross@xvid.org)
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * Microsoft Windows ICO demuxer
24
+ */
25
+
26
+#include "libavutil/intreadwrite.h"
27
+#include "libavcodec/bytestream.h"
28
+#include "libavcodec/bmp.h"
29
+#include "avformat.h"
30
+#include "internal.h"
31
+
32
+typedef struct {
33
+    int offset;
34
+    int size;
35
+    int nb_pal;
36
+} IcoImage;
37
+
38
+typedef struct {
39
+    int current_image;
40
+    int nb_images;
41
+    IcoImage * images;
42
+} IcoDemuxContext;
43
+
44
+static int probe(AVProbeData *p)
45
+{
46
+    if (AV_RL16(p->buf) == 0 && AV_RL16(p->buf + 2) == 1 && AV_RL16(p->buf + 4))
47
+        return AVPROBE_SCORE_MAX / 3;
48
+    return 0;
49
+}
50
+
51
+static int read_header(AVFormatContext *s, AVFormatParameters *ap)
52
+{
53
+    IcoDemuxContext *ico = s->priv_data;
54
+    AVIOContext *pb = s->pb;
55
+    int i;
56
+
57
+    avio_skip(pb, 4);
58
+    ico->nb_images = avio_rl16(pb);
59
+
60
+    ico->images = av_malloc(ico->nb_images * sizeof(IcoImage));
61
+    if (!ico->images)
62
+        return AVERROR(ENOMEM);
63
+
64
+    for (i = 0; i < ico->nb_images; i++) {
65
+        AVStream *st;
66
+
67
+        if (avio_seek(pb, 6 + i * 16, SEEK_SET) < 0)
68
+            break;
69
+
70
+        st = avformat_new_stream(s, NULL);
71
+        if (!st)
72
+            return AVERROR(ENOMEM);
73
+
74
+        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
75
+        st->codec->width      = avio_r8(pb);
76
+        st->codec->height     = avio_r8(pb);
77
+        ico->images[i].nb_pal = avio_r8(pb);
78
+
79
+        avio_skip(pb, 3);
80
+        st->codec->bits_per_coded_sample = avio_rl16(pb);
81
+        if (st->codec->bits_per_coded_sample <= 8 && !ico->images[i].nb_pal)
82
+            ico->images[i].nb_pal = 1 << st->codec->bits_per_coded_sample;
83
+
84
+        ico->images[i].size   = avio_rl32(pb);
85
+        ico->images[i].offset = avio_rl32(pb);
86
+
87
+        if (avio_seek(pb, ico->images[i].offset, SEEK_SET) < 0)
88
+            break;
89
+
90
+        switch(avio_rl32(pb)) {
91
+        case MKTAG(0x89, 'P', 'N', 'G'):
92
+            st->codec->codec_id = CODEC_ID_PNG;
93
+            st->codec->width    = 0;
94
+            st->codec->height   = 0;
95
+            break;
96
+        case 40:
97
+            st->codec->codec_id = CODEC_ID_BMP;
98
+            if (!st->codec->width || !st->codec->height) {
99
+                st->codec->width  = avio_rl32(pb);
100
+                st->codec->height = avio_rl32(pb) / 2;
101
+            }
102
+            break;
103
+        default:
104
+            av_log_ask_for_sample(s, "unsupported codec\n");
105
+            return AVERROR_INVALIDDATA;
106
+        }
107
+    }
108
+
109
+    return 0;
110
+}
111
+
112
+static int read_packet(AVFormatContext *s, AVPacket *pkt)
113
+{
114
+    IcoDemuxContext *ico = s->priv_data;
115
+    IcoImage *image;
116
+    AVIOContext *pb = s->pb;
117
+    int ret;
118
+
119
+    if (ico->current_image >= ico->nb_images)
120
+        return AVERROR(EIO);
121
+
122
+    image = &ico->images[ico->current_image];
123
+
124
+    if ((ret = avio_seek(pb, image->offset, SEEK_SET)) < 0)
125
+        return ret;
126
+
127
+    if (s->streams[ico->current_image]->codec->codec_id == CODEC_ID_PNG) {
128
+        if ((ret = av_get_packet(pb, pkt, image->size)) < 0)
129
+            return ret;
130
+    } else {
131
+        uint8_t *buf;
132
+        if ((ret = av_new_packet(pkt, 14 + image->size)) < 0)
133
+            return ret;
134
+        buf = pkt->data;
135
+
136
+        /* add BMP header */
137
+        bytestream_put_byte(&buf, 'B');
138
+        bytestream_put_byte(&buf, 'M');
139
+        bytestream_put_le32(&buf, pkt->size);
140
+        bytestream_put_le16(&buf, 0);
141
+        bytestream_put_le16(&buf, 0);
142
+        bytestream_put_le32(&buf, 14 + 40 + image->nb_pal * 4);
143
+
144
+        if ((ret = avio_read(pb, buf, image->size)) < 0)
145
+            return ret;
146
+
147
+        AV_WL32(buf + 8, AV_RL32(buf + 8) / 2);
148
+        AV_WL32(buf + 32, image->nb_pal);
149
+    }
150
+
151
+    pkt->stream_index = ico->current_image++;
152
+    pkt->flags |= AV_PKT_FLAG_KEY;
153
+
154
+    return 0;
155
+}
156
+
157
+AVInputFormat ff_ico_demuxer = {
158
+    .name           = "ico",
159
+    .long_name      = NULL_IF_CONFIG_SMALL("Microsoft Windows ICO"),
160
+    .priv_data_size = sizeof(IcoDemuxContext),
161
+    .read_probe     = probe,
162
+    .read_header    = read_header,
163
+    .read_packet    = read_packet,
164
+    .flags          = AVFMT_NOTIMESTAMPS,
165
+};