annotate ffmpeg/libavformat/icodec.c @ 13:844d341cf643 tip

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