Statistics
| Branch: | Revision:

ffmpeg / libavcodec / iff.c @ 9f1d760a

History | View | Annotate | Download (6.54 KB)

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
                    int8_t 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
                int8_t 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
};