You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
6.5KB

  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. * @file
  23. * Microsoft Windows ICO demuxer
  24. */
  25. #include "libavutil/intreadwrite.h"
  26. #include "libavcodec/bytestream.h"
  27. #include "libavcodec/bmp.h"
  28. #include "libavcodec/png.h"
  29. #include "avformat.h"
  30. #include "internal.h"
  31. typedef struct {
  32. int offset;
  33. int size;
  34. int nb_pal;
  35. } IcoImage;
  36. typedef struct {
  37. int current_image;
  38. int nb_images;
  39. IcoImage * images;
  40. } IcoDemuxContext;
  41. static int probe(const AVProbeData *p)
  42. {
  43. unsigned i, frames, checked = 0;
  44. if (p->buf_size < 22 || AV_RL16(p->buf) || AV_RL16(p->buf + 2) != 1)
  45. return 0;
  46. frames = AV_RL16(p->buf + 4);
  47. if (!frames)
  48. return 0;
  49. for (i = 0; i < frames && i * 16 + 22 <= p->buf_size; i++) {
  50. unsigned offset;
  51. if (AV_RL16(p->buf + 10 + i * 16) & ~1)
  52. return FFMIN(i, AVPROBE_SCORE_MAX / 4);
  53. if (p->buf[13 + i * 16])
  54. return FFMIN(i, AVPROBE_SCORE_MAX / 4);
  55. if (AV_RL32(p->buf + 14 + i * 16) < 40)
  56. return FFMIN(i, AVPROBE_SCORE_MAX / 4);
  57. offset = AV_RL32(p->buf + 18 + i * 16);
  58. if (offset < 22)
  59. return FFMIN(i, AVPROBE_SCORE_MAX / 4);
  60. if (offset > p->buf_size - 8)
  61. continue;
  62. if (p->buf[offset] != 40 && AV_RB64(p->buf + offset) != PNGSIG)
  63. return FFMIN(i, AVPROBE_SCORE_MAX / 4);
  64. checked++;
  65. }
  66. if (checked < frames)
  67. return AVPROBE_SCORE_MAX / 4 + FFMIN(checked, 1);
  68. return AVPROBE_SCORE_MAX / 2 + 1;
  69. }
  70. static int read_header(AVFormatContext *s)
  71. {
  72. IcoDemuxContext *ico = s->priv_data;
  73. AVIOContext *pb = s->pb;
  74. int i, codec;
  75. avio_skip(pb, 4);
  76. ico->nb_images = avio_rl16(pb);
  77. ico->images = av_malloc_array(ico->nb_images, sizeof(IcoImage));
  78. if (!ico->images)
  79. return AVERROR(ENOMEM);
  80. for (i = 0; i < ico->nb_images; i++) {
  81. AVStream *st;
  82. int tmp;
  83. if (avio_seek(pb, 6 + i * 16, SEEK_SET) < 0)
  84. break;
  85. st = avformat_new_stream(s, NULL);
  86. if (!st) {
  87. av_freep(&ico->images);
  88. return AVERROR(ENOMEM);
  89. }
  90. st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  91. st->codecpar->width = avio_r8(pb);
  92. st->codecpar->height = avio_r8(pb);
  93. ico->images[i].nb_pal = avio_r8(pb);
  94. if (ico->images[i].nb_pal == 255)
  95. ico->images[i].nb_pal = 0;
  96. avio_skip(pb, 5);
  97. ico->images[i].size = avio_rl32(pb);
  98. if (ico->images[i].size <= 0) {
  99. av_log(s, AV_LOG_ERROR, "Invalid image size %d\n", ico->images[i].size);
  100. av_freep(&ico->images);
  101. return AVERROR_INVALIDDATA;
  102. }
  103. ico->images[i].offset = avio_rl32(pb);
  104. if (avio_seek(pb, ico->images[i].offset, SEEK_SET) < 0)
  105. break;
  106. codec = avio_rl32(pb);
  107. switch (codec) {
  108. case MKTAG(0x89, 'P', 'N', 'G'):
  109. st->codecpar->codec_id = AV_CODEC_ID_PNG;
  110. st->codecpar->width = 0;
  111. st->codecpar->height = 0;
  112. break;
  113. case 40:
  114. if (ico->images[i].size < 40) {
  115. av_freep(&ico->images);
  116. return AVERROR_INVALIDDATA;
  117. }
  118. st->codecpar->codec_id = AV_CODEC_ID_BMP;
  119. tmp = avio_rl32(pb);
  120. if (tmp)
  121. st->codecpar->width = tmp;
  122. tmp = avio_rl32(pb);
  123. if (tmp)
  124. st->codecpar->height = tmp / 2;
  125. break;
  126. default:
  127. avpriv_request_sample(s, "codec %d", codec);
  128. av_freep(&ico->images);
  129. return AVERROR_INVALIDDATA;
  130. }
  131. }
  132. return 0;
  133. }
  134. static int read_packet(AVFormatContext *s, AVPacket *pkt)
  135. {
  136. IcoDemuxContext *ico = s->priv_data;
  137. IcoImage *image;
  138. AVIOContext *pb = s->pb;
  139. AVStream *st = s->streams[0];
  140. int ret;
  141. if (ico->current_image >= ico->nb_images)
  142. return AVERROR_EOF;
  143. image = &ico->images[ico->current_image];
  144. if ((ret = avio_seek(pb, image->offset, SEEK_SET)) < 0)
  145. return ret;
  146. if (s->streams[ico->current_image]->codecpar->codec_id == AV_CODEC_ID_PNG) {
  147. if ((ret = av_get_packet(pb, pkt, image->size)) < 0)
  148. return ret;
  149. } else {
  150. uint8_t *buf;
  151. if ((ret = av_new_packet(pkt, 14 + image->size)) < 0)
  152. return ret;
  153. buf = pkt->data;
  154. /* add BMP header */
  155. bytestream_put_byte(&buf, 'B');
  156. bytestream_put_byte(&buf, 'M');
  157. bytestream_put_le32(&buf, pkt->size);
  158. bytestream_put_le16(&buf, 0);
  159. bytestream_put_le16(&buf, 0);
  160. bytestream_put_le32(&buf, 0);
  161. if ((ret = avio_read(pb, buf, image->size)) != image->size) {
  162. return ret < 0 ? ret : AVERROR_INVALIDDATA;
  163. }
  164. st->codecpar->bits_per_coded_sample = AV_RL16(buf + 14);
  165. if (AV_RL32(buf + 32))
  166. image->nb_pal = AV_RL32(buf + 32);
  167. if (st->codecpar->bits_per_coded_sample <= 8 && !image->nb_pal) {
  168. image->nb_pal = 1 << st->codecpar->bits_per_coded_sample;
  169. AV_WL32(buf + 32, image->nb_pal);
  170. }
  171. AV_WL32(buf - 4, 14 + 40 + image->nb_pal * 4);
  172. AV_WL32(buf + 8, AV_RL32(buf + 8) / 2);
  173. }
  174. pkt->stream_index = ico->current_image++;
  175. pkt->flags |= AV_PKT_FLAG_KEY;
  176. return 0;
  177. }
  178. static int ico_read_close(AVFormatContext * s)
  179. {
  180. IcoDemuxContext *ico = s->priv_data;
  181. av_freep(&ico->images);
  182. return 0;
  183. }
  184. AVInputFormat ff_ico_demuxer = {
  185. .name = "ico",
  186. .long_name = NULL_IF_CONFIG_SMALL("Microsoft Windows ICO"),
  187. .priv_data_size = sizeof(IcoDemuxContext),
  188. .read_probe = probe,
  189. .read_header = read_header,
  190. .read_packet = read_packet,
  191. .read_close = ico_read_close,
  192. .flags = AVFMT_NOTIMESTAMPS,
  193. };