11074
|
1 /*
|
|
2 * IFF PBM/ILBM bitmap decoder
|
|
3 * Copyright (c) 2010 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 libavcodec/iff.c
|
|
24 * IFF PBM/ILBM bitmap decoder
|
|
25 */
|
|
26
|
|
27 #include "bytestream.h"
|
|
28 #include "avcodec.h"
|
|
29
|
|
30 /**
|
|
31 * Convert CMAP buffer (stored in extradata) to lavc palette format
|
|
32 */
|
|
33 int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
|
|
34 {
|
|
35 int count, i;
|
|
36
|
|
37 if (avctx->bits_per_coded_sample > 8) {
|
|
38 av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
|
|
39 return AVERROR_INVALIDDATA;
|
|
40 }
|
|
41
|
|
42 count = 1 << avctx->bits_per_coded_sample;
|
|
43 if (avctx->extradata_size < count * 3) {
|
|
44 av_log(avctx, AV_LOG_ERROR, "palette data underflow\n");
|
|
45 return AVERROR_INVALIDDATA;
|
|
46 }
|
|
47 for (i=0; i < count; i++) {
|
|
48 pal[i] = AV_RB24( avctx->extradata + i*3 );
|
|
49 }
|
|
50 return 0;
|
|
51 }
|
|
52
|
|
53 static av_cold int decode_init(AVCodecContext *avctx)
|
|
54 {
|
|
55 AVFrame *frame = avctx->priv_data;
|
|
56
|
|
57 avctx->pix_fmt = PIX_FMT_PAL8;
|
|
58 frame->reference = 1;
|
|
59
|
|
60 if (avctx->get_buffer(avctx, frame) < 0) {
|
|
61 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
|
62 return AVERROR_UNKNOWN;
|
|
63 }
|
|
64 return ff_cmap_read_palette(avctx, (uint32_t*)frame->data[1]);
|
|
65 }
|
|
66
|
|
67 /**
|
|
68 * Interleaved memcpy
|
|
69 */
|
|
70 static void imemcpy(uint8_t *dst, const uint8_t const *buf, int x, int bps, int plane, int length)
|
|
71 {
|
|
72 int i, b;
|
|
73 for(i = 0; i < length; i++) {
|
|
74 int value = buf[i];
|
|
75 for (b = 0; b < bps; b++) {
|
|
76 if (value & (1<<b))
|
|
77 dst[ (x+i)*bps + 7 - b] |= 1<<plane;
|
|
78 }
|
|
79 }
|
|
80 }
|
|
81
|
|
82 /**
|
|
83 * Interleaved memset
|
|
84 */
|
|
85 static void imemset(uint8_t *dst, int value, int x, int bps, int plane, int length)
|
|
86 {
|
|
87 int i, b;
|
|
88 for(i = 0; i < length; i++) {
|
|
89 for (b = 0; b < bps; b++) {
|
|
90 if (value & (1<<b))
|
|
91 dst[ (x+i)*bps + 7 - b] |= 1<<plane;
|
|
92 }
|
|
93 }
|
|
94 }
|
|
95
|
|
96 static int decode_frame_ilbm(AVCodecContext *avctx,
|
|
97 void *data, int *data_size,
|
|
98 AVPacket *avpkt)
|
|
99 {
|
|
100 AVFrame *frame = avctx->priv_data;
|
|
101 const uint8_t *buf = avpkt->data;
|
|
102 int buf_size = avpkt->size;
|
|
103 int planewidth = avctx->width / avctx->bits_per_coded_sample;
|
|
104 int y, plane;
|
|
105
|
|
106 if (avctx->reget_buffer(avctx, frame) < 0){
|
|
107 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
|
108 return -1;
|
|
109 }
|
|
110
|
|
111 if (buf_size < avctx->width * avctx->height) {
|
|
112 av_log(avctx, AV_LOG_ERROR, "buffer underflow\n");
|
|
113 return -1;
|
|
114 }
|
|
115
|
|
116 for(y = 0; y < avctx->height; y++ ) {
|
|
117 uint8_t *row = &frame->data[0][ y*frame->linesize[0] ];
|
|
118 memset(row, 0, avctx->width);
|
|
119 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
|
|
120 imemcpy(row, buf, 0, avctx->bits_per_coded_sample, plane, planewidth);
|
|
121 buf += planewidth;
|
|
122 }
|
|
123 }
|
|
124
|
|
125 *data_size = sizeof(AVFrame);
|
|
126 *(AVFrame*)data = *frame;
|
|
127 return buf_size;
|
|
128 }
|
|
129
|
|
130 static int decode_frame_byterun1(AVCodecContext *avctx,
|
|
131 void *data, int *data_size,
|
|
132 AVPacket *avpkt)
|
|
133 {
|
|
134 AVFrame *frame = avctx->priv_data;
|
|
135 const uint8_t *buf = avpkt->data;
|
|
136 int buf_size = avpkt->size;
|
|
137 const uint8_t *buf_end = buf+buf_size;
|
|
138 int planewidth = avctx->width / avctx->bits_per_coded_sample;
|
|
139 int y, plane, x;
|
|
140
|
|
141 if (avctx->reget_buffer(avctx, frame) < 0){
|
|
142 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
|
143 return -1;
|
|
144 }
|
|
145
|
|
146 for(y = 0; y < avctx->height ; y++ ) {
|
|
147 uint8_t *row = &frame->data[0][ y*frame->linesize[0] ];
|
|
148 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
|
|
149 memset(row, 0, avctx->width);
|
|
150 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
|
|
151 for(x = 0; x < planewidth && buf < buf_end; ) {
|
|
152 char value = *buf++;
|
|
153 int length;
|
|
154 if (value >= 0) {
|
|
155 length = value + 1;
|
|
156 imemcpy(row, buf, x, avctx->bits_per_coded_sample, plane, FFMIN3(length, buf_end - buf, planewidth - x));
|
|
157 buf += length;
|
|
158 } else if (value > -128) {
|
|
159 length = -value + 1;
|
|
160 imemset(row, *buf++, x, avctx->bits_per_coded_sample, plane, FFMIN(length, planewidth - x));
|
|
161 } else { //noop
|
|
162 continue;
|
|
163 }
|
|
164 x += length;
|
|
165 }
|
|
166 }
|
|
167 } else {
|
|
168 for(x = 0; x < avctx->width && buf < buf_end; ) {
|
|
169 char value = *buf++;
|
|
170 int length;
|
|
171 if (value >= 0) {
|
|
172 length = value + 1;
|
|
173 memcpy(row + x, buf, FFMIN3(length, buf_end - buf, avctx->width - x));
|
|
174 buf += length;
|
|
175 } else if (value > -128) {
|
|
176 length = -value + 1;
|
|
177 memset(row + x, *buf++, FFMIN(length, avctx->width - x));
|
|
178 } else { //noop
|
|
179 continue;
|
|
180 }
|
|
181 x += length;
|
|
182 }
|
|
183 }
|
|
184 }
|
|
185
|
|
186 *data_size = sizeof(AVFrame);
|
|
187 *(AVFrame*)data = *frame;
|
|
188 return buf_size;
|
|
189 }
|
|
190
|
|
191 static av_cold int decode_end(AVCodecContext *avctx)
|
|
192 {
|
|
193 AVFrame *frame = avctx->priv_data;
|
|
194 if (frame->data[0])
|
|
195 avctx->release_buffer(avctx, frame);
|
|
196 return 0;
|
|
197 }
|
|
198
|
|
199 AVCodec iff_ilbm_decoder = {
|
|
200 "iff_ilbm",
|
|
201 CODEC_TYPE_VIDEO,
|
|
202 CODEC_ID_IFF_ILBM,
|
|
203 sizeof(AVFrame),
|
|
204 decode_init,
|
|
205 NULL,
|
|
206 decode_end,
|
|
207 decode_frame_ilbm,
|
|
208 CODEC_CAP_DR1,
|
|
209 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
|
|
210 };
|
|
211
|
|
212 AVCodec iff_byterun1_decoder = {
|
|
213 "iff_byterun1",
|
|
214 CODEC_TYPE_VIDEO,
|
|
215 CODEC_ID_IFF_BYTERUN1,
|
|
216 sizeof(AVFrame),
|
|
217 decode_init,
|
|
218 NULL,
|
|
219 decode_end,
|
|
220 decode_frame_byterun1,
|
|
221 CODEC_CAP_DR1,
|
|
222 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
|
|
223 };
|