1/* 2 * Microsoft Windows ICO demuxer 3 * Copyright (c) 2011 Peter Ross (pross@xvid.org) 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Microsoft Windows ICO demuxer 25 */ 26 27#include "libavutil/intreadwrite.h" 28#include "libavcodec/bytestream.h" 29#include "libavcodec/bmp.h" 30#include "avformat.h" 31#include "internal.h" 32 33typedef struct { 34 int offset; 35 int size; 36 int nb_pal; 37} IcoImage; 38 39typedef struct { 40 int current_image; 41 int nb_images; 42 IcoImage * images; 43} IcoDemuxContext; 44 45static int probe(AVProbeData *p) 46{ 47 if (AV_RL16(p->buf) == 0 && AV_RL16(p->buf + 2) == 1 && AV_RL16(p->buf + 4)) 48 return AVPROBE_SCORE_MAX / 4; 49 return 0; 50} 51 52static int read_header(AVFormatContext *s) 53{ 54 IcoDemuxContext *ico = s->priv_data; 55 AVIOContext *pb = s->pb; 56 int i, codec; 57 58 avio_skip(pb, 4); 59 ico->nb_images = avio_rl16(pb); 60 61 ico->images = av_malloc_array(ico->nb_images, sizeof(IcoImage)); 62 if (!ico->images) 63 return AVERROR(ENOMEM); 64 65 for (i = 0; i < ico->nb_images; i++) { 66 AVStream *st; 67 int tmp; 68 69 if (avio_seek(pb, 6 + i * 16, SEEK_SET) < 0) 70 break; 71 72 st = avformat_new_stream(s, NULL); 73 if (!st) 74 return AVERROR(ENOMEM); 75 76 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 77 st->codec->width = avio_r8(pb); 78 st->codec->height = avio_r8(pb); 79 ico->images[i].nb_pal = avio_r8(pb); 80 if (ico->images[i].nb_pal == 255) 81 ico->images[i].nb_pal = 0; 82 83 avio_skip(pb, 5); 84 85 ico->images[i].size = avio_rl32(pb); 86 ico->images[i].offset = avio_rl32(pb); 87 88 if (avio_seek(pb, ico->images[i].offset, SEEK_SET) < 0) 89 break; 90 91 codec = avio_rl32(pb); 92 switch (codec) { 93 case MKTAG(0x89, 'P', 'N', 'G'): 94 st->codec->codec_id = AV_CODEC_ID_PNG; 95 st->codec->width = 0; 96 st->codec->height = 0; 97 break; 98 case 40: 99 if (ico->images[i].size < 40) 100 return AVERROR_INVALIDDATA; 101 st->codec->codec_id = AV_CODEC_ID_BMP; 102 tmp = avio_rl32(pb); 103 if (tmp) 104 st->codec->width = tmp; 105 tmp = avio_rl32(pb); 106 if (tmp) 107 st->codec->height = tmp / 2; 108 break; 109 default: 110 avpriv_request_sample(s, "codec %d", codec); 111 return AVERROR_INVALIDDATA; 112 } 113 } 114 115 return 0; 116} 117 118static int read_packet(AVFormatContext *s, AVPacket *pkt) 119{ 120 IcoDemuxContext *ico = s->priv_data; 121 IcoImage *image; 122 AVIOContext *pb = s->pb; 123 AVStream *st = s->streams[0]; 124 int ret; 125 126 if (ico->current_image >= ico->nb_images) 127 return AVERROR(EIO); 128 129 image = &ico->images[ico->current_image]; 130 131 if ((ret = avio_seek(pb, image->offset, SEEK_SET)) < 0) 132 return ret; 133 134 if (s->streams[ico->current_image]->codec->codec_id == AV_CODEC_ID_PNG) { 135 if ((ret = av_get_packet(pb, pkt, image->size)) < 0) 136 return ret; 137 } else { 138 uint8_t *buf; 139 if ((ret = av_new_packet(pkt, 14 + image->size)) < 0) 140 return ret; 141 buf = pkt->data; 142 143 /* add BMP header */ 144 bytestream_put_byte(&buf, 'B'); 145 bytestream_put_byte(&buf, 'M'); 146 bytestream_put_le32(&buf, pkt->size); 147 bytestream_put_le16(&buf, 0); 148 bytestream_put_le16(&buf, 0); 149 bytestream_put_le32(&buf, 0); 150 151 if ((ret = avio_read(pb, buf, image->size)) < 0) 152 return ret; 153 154 st->codec->bits_per_coded_sample = AV_RL16(buf + 14); 155 156 if (AV_RL32(buf + 32)) 157 image->nb_pal = AV_RL32(buf + 32); 158 159 if (st->codec->bits_per_coded_sample <= 8 && !image->nb_pal) { 160 image->nb_pal = 1 << st->codec->bits_per_coded_sample; 161 AV_WL32(buf + 32, image->nb_pal); 162 } 163 164 AV_WL32(buf - 4, 14 + 40 + image->nb_pal * 4); 165 AV_WL32(buf + 8, AV_RL32(buf + 8) / 2); 166 } 167 168 pkt->stream_index = ico->current_image++; 169 pkt->flags |= AV_PKT_FLAG_KEY; 170 171 return 0; 172} 173 174AVInputFormat ff_ico_demuxer = { 175 .name = "ico", 176 .long_name = NULL_IF_CONFIG_SMALL("Microsoft Windows ICO"), 177 .priv_data_size = sizeof(IcoDemuxContext), 178 .read_probe = probe, 179 .read_header = read_header, 180 .read_packet = read_packet, 181 .flags = AVFMT_NOTIMESTAMPS, 182}; 183