~ubuntu-branches/ubuntu/trusty/libav/trusty

« back to all changes in this revision

Viewing changes to libavcodec/cdxl.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2013-10-22 23:24:08 UTC
  • mfrom: (1.3.36 sid)
  • Revision ID: package-import@ubuntu.com-20131022232408-b8tvvn4pyzri9mi3
Tags: 6:9.10-1ubuntu1
* Build all -extra flavors from this source package, as libav got demoted
  from main to universe, cf LP: #1243235
* Simplify debian/rules to follow exactly the code that debian executes
* New upstream (LP: #1180288) fixes lots of security issues (LP: #1242802)
* Merge from unstable, remaining changes:
  - build-depend on libtiff5-dev rather than libtiff4-dev,
    avoids FTBFS caused by imlib
  - follow the regular debian codepaths

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * CDXL video decoder
 
3
 * Copyright (c) 2011-2012 Paul B Mahol
 
4
 *
 
5
 * This file is part of Libav.
 
6
 *
 
7
 * Libav 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
 * Libav 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 Libav; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
20
 */
 
21
 
 
22
#include "libavutil/intreadwrite.h"
 
23
#include "libavutil/imgutils.h"
 
24
#include "avcodec.h"
 
25
#include "get_bits.h"
 
26
#include "internal.h"
 
27
 
 
28
#define BIT_PLANAR   0x00
 
29
#define BYTE_PLANAR  0x20
 
30
#define CHUNKY       0x40
 
31
#define BIT_LINE     0x80
 
32
#define BYTE_LINE    0xC0
 
33
 
 
34
typedef struct {
 
35
    AVCodecContext *avctx;
 
36
    AVFrame        frame;
 
37
    int            bpp;
 
38
    int            format;
 
39
    int            padded_bits;
 
40
    const uint8_t  *palette;
 
41
    int            palette_size;
 
42
    const uint8_t  *video;
 
43
    int            video_size;
 
44
    uint8_t        *new_video;
 
45
    int            new_video_size;
 
46
} CDXLVideoContext;
 
47
 
 
48
static av_cold int cdxl_decode_init(AVCodecContext *avctx)
 
49
{
 
50
    CDXLVideoContext *c = avctx->priv_data;
 
51
 
 
52
    avcodec_get_frame_defaults(&c->frame);
 
53
    c->new_video_size = 0;
 
54
    c->avctx          = avctx;
 
55
 
 
56
    return 0;
 
57
}
 
58
 
 
59
static void import_palette(CDXLVideoContext *c, uint32_t *new_palette)
 
60
{
 
61
    int i;
 
62
 
 
63
    for (i = 0; i < c->palette_size / 2; i++) {
 
64
        unsigned rgb = AV_RB16(&c->palette[i * 2]);
 
65
        unsigned r   = ((rgb >> 8) & 0xF) * 0x11;
 
66
        unsigned g   = ((rgb >> 4) & 0xF) * 0x11;
 
67
        unsigned b   =  (rgb       & 0xF) * 0x11;
 
68
        AV_WN32(&new_palette[i], (r << 16) | (g << 8) | b);
 
69
    }
 
70
}
 
71
 
 
72
static void bitplanar2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
 
73
{
 
74
    GetBitContext gb;
 
75
    int x, y, plane;
 
76
 
 
77
    init_get_bits(&gb, c->video, c->video_size * 8);
 
78
    for (plane = 0; plane < c->bpp; plane++) {
 
79
        for (y = 0; y < c->avctx->height; y++) {
 
80
            for (x = 0; x < c->avctx->width; x++)
 
81
                out[linesize * y + x] |= get_bits1(&gb) << plane;
 
82
            skip_bits(&gb, c->padded_bits);
 
83
        }
 
84
    }
 
85
}
 
86
 
 
87
static void bitline2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
 
88
{
 
89
    GetBitContext  gb;
 
90
    int x, y, plane;
 
91
 
 
92
    init_get_bits(&gb, c->video, c->video_size * 8);
 
93
    for (y = 0; y < c->avctx->height; y++) {
 
94
        for (plane = 0; plane < c->bpp; plane++) {
 
95
            for (x = 0; x < c->avctx->width; x++)
 
96
                out[linesize * y + x] |= get_bits1(&gb) << plane;
 
97
            skip_bits(&gb, c->padded_bits);
 
98
        }
 
99
    }
 
100
}
 
101
 
 
102
static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out)
 
103
{
 
104
    memset(out, 0, linesize * c->avctx->height);
 
105
 
 
106
    switch (c->format) {
 
107
    case BIT_PLANAR:
 
108
        bitplanar2chunky(c, linesize, out);
 
109
        break;
 
110
    case BIT_LINE:
 
111
        bitline2chunky(c, linesize, out);
 
112
        break;
 
113
    }
 
114
}
 
115
 
 
116
static void cdxl_decode_rgb(CDXLVideoContext *c)
 
117
{
 
118
    uint32_t *new_palette = (uint32_t *)c->frame.data[1];
 
119
 
 
120
    import_palette(c, new_palette);
 
121
    import_format(c, c->frame.linesize[0], c->frame.data[0]);
 
122
}
 
123
 
 
124
static void cdxl_decode_ham6(CDXLVideoContext *c)
 
125
{
 
126
    AVCodecContext *avctx = c->avctx;
 
127
    uint32_t new_palette[16], r, g, b;
 
128
    uint8_t *ptr, *out, index, op;
 
129
    int x, y;
 
130
 
 
131
    ptr = c->new_video;
 
132
    out = c->frame.data[0];
 
133
 
 
134
    import_palette(c, new_palette);
 
135
    import_format(c, avctx->width, c->new_video);
 
136
 
 
137
    for (y = 0; y < avctx->height; y++) {
 
138
        r = new_palette[0] & 0xFF0000;
 
139
        g = new_palette[0] & 0xFF00;
 
140
        b = new_palette[0] & 0xFF;
 
141
        for (x = 0; x < avctx->width; x++) {
 
142
            index  = *ptr++;
 
143
            op     = index >> 4;
 
144
            index &= 15;
 
145
            switch (op) {
 
146
            case 0:
 
147
                r = new_palette[index] & 0xFF0000;
 
148
                g = new_palette[index] & 0xFF00;
 
149
                b = new_palette[index] & 0xFF;
 
150
                break;
 
151
            case 1:
 
152
                b = index * 0x11;
 
153
                break;
 
154
            case 2:
 
155
                r = index * 0x11 << 16;
 
156
                break;
 
157
            case 3:
 
158
                g = index * 0x11 << 8;
 
159
                break;
 
160
            }
 
161
            AV_WL24(out + x * 3, r | g | b);
 
162
        }
 
163
        out += c->frame.linesize[0];
 
164
    }
 
165
}
 
166
 
 
167
static void cdxl_decode_ham8(CDXLVideoContext *c)
 
168
{
 
169
    AVCodecContext *avctx = c->avctx;
 
170
    uint32_t new_palette[64], r, g, b;
 
171
    uint8_t *ptr, *out, index, op;
 
172
    int x, y;
 
173
 
 
174
    ptr = c->new_video;
 
175
    out = c->frame.data[0];
 
176
 
 
177
    import_palette(c, new_palette);
 
178
    import_format(c, avctx->width, c->new_video);
 
179
 
 
180
    for (y = 0; y < avctx->height; y++) {
 
181
        r = new_palette[0] & 0xFF0000;
 
182
        g = new_palette[0] & 0xFF00;
 
183
        b = new_palette[0] & 0xFF;
 
184
        for (x = 0; x < avctx->width; x++) {
 
185
            index  = *ptr++;
 
186
            op     = index >> 6;
 
187
            index &= 63;
 
188
            switch (op) {
 
189
            case 0:
 
190
                r = new_palette[index] & 0xFF0000;
 
191
                g = new_palette[index] & 0xFF00;
 
192
                b = new_palette[index] & 0xFF;
 
193
                break;
 
194
            case 1:
 
195
                b = (index <<  2) | (b & 3);
 
196
                break;
 
197
            case 2:
 
198
                r = (index << 18) | (r & (3 << 16));
 
199
                break;
 
200
            case 3:
 
201
                g = (index << 10) | (g & (3 << 8));
 
202
                break;
 
203
            }
 
204
            AV_WL24(out + x * 3, r | g | b);
 
205
        }
 
206
        out += c->frame.linesize[0];
 
207
    }
 
208
}
 
209
 
 
210
static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
 
211
                             int *got_frame, AVPacket *pkt)
 
212
{
 
213
    CDXLVideoContext *c = avctx->priv_data;
 
214
    AVFrame * const p = &c->frame;
 
215
    int ret, w, h, encoding, aligned_width, buf_size = pkt->size;
 
216
    const uint8_t *buf = pkt->data;
 
217
 
 
218
    if (buf_size < 32)
 
219
        return AVERROR_INVALIDDATA;
 
220
    encoding        = buf[1] & 7;
 
221
    c->format       = buf[1] & 0xE0;
 
222
    w               = AV_RB16(&buf[14]);
 
223
    h               = AV_RB16(&buf[16]);
 
224
    c->bpp          = buf[19];
 
225
    c->palette_size = AV_RB16(&buf[20]);
 
226
    c->palette      = buf + 32;
 
227
    c->video        = c->palette + c->palette_size;
 
228
    c->video_size   = buf_size - c->palette_size - 32;
 
229
 
 
230
    if (c->palette_size > 512)
 
231
        return AVERROR_INVALIDDATA;
 
232
    if (buf_size < c->palette_size + 32)
 
233
        return AVERROR_INVALIDDATA;
 
234
    if (c->bpp < 1)
 
235
        return AVERROR_INVALIDDATA;
 
236
    if (c->format != BIT_PLANAR && c->format != BIT_LINE) {
 
237
        av_log_ask_for_sample(avctx, "unsupported pixel format: 0x%0x\n", c->format);
 
238
        return AVERROR_PATCHWELCOME;
 
239
    }
 
240
 
 
241
    if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
 
242
        return ret;
 
243
    if (w != avctx->width || h != avctx->height)
 
244
        avcodec_set_dimensions(avctx, w, h);
 
245
 
 
246
    aligned_width = FFALIGN(c->avctx->width, 16);
 
247
    c->padded_bits  = aligned_width - c->avctx->width;
 
248
    if (c->video_size < aligned_width * avctx->height * c->bpp / 8)
 
249
        return AVERROR_INVALIDDATA;
 
250
    if (!encoding && c->palette_size && c->bpp <= 8) {
 
251
        avctx->pix_fmt = AV_PIX_FMT_PAL8;
 
252
    } else if (encoding == 1 && (c->bpp == 6 || c->bpp == 8)) {
 
253
        if (c->palette_size != (1 << (c->bpp - 1)))
 
254
            return AVERROR_INVALIDDATA;
 
255
        avctx->pix_fmt = AV_PIX_FMT_BGR24;
 
256
    } else {
 
257
        av_log_ask_for_sample(avctx, "unsupported encoding %d and bpp %d\n",
 
258
                              encoding, c->bpp);
 
259
        return AVERROR_PATCHWELCOME;
 
260
    }
 
261
 
 
262
    if (p->data[0])
 
263
        avctx->release_buffer(avctx, p);
 
264
 
 
265
    p->reference = 0;
 
266
    if ((ret = ff_get_buffer(avctx, p)) < 0) {
 
267
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 
268
        return ret;
 
269
    }
 
270
    p->pict_type = AV_PICTURE_TYPE_I;
 
271
 
 
272
    if (encoding) {
 
273
        av_fast_padded_malloc(&c->new_video, &c->new_video_size,
 
274
                              h * w + FF_INPUT_BUFFER_PADDING_SIZE);
 
275
        if (!c->new_video)
 
276
            return AVERROR(ENOMEM);
 
277
        if (c->bpp == 8)
 
278
            cdxl_decode_ham8(c);
 
279
        else
 
280
            cdxl_decode_ham6(c);
 
281
    } else {
 
282
        cdxl_decode_rgb(c);
 
283
    }
 
284
    *got_frame = 1;
 
285
    *(AVFrame*)data = c->frame;
 
286
 
 
287
    return buf_size;
 
288
}
 
289
 
 
290
static av_cold int cdxl_decode_end(AVCodecContext *avctx)
 
291
{
 
292
    CDXLVideoContext *c = avctx->priv_data;
 
293
 
 
294
    av_free(c->new_video);
 
295
    if (c->frame.data[0])
 
296
        avctx->release_buffer(avctx, &c->frame);
 
297
 
 
298
    return 0;
 
299
}
 
300
 
 
301
AVCodec ff_cdxl_decoder = {
 
302
    .name           = "cdxl",
 
303
    .type           = AVMEDIA_TYPE_VIDEO,
 
304
    .id             = AV_CODEC_ID_CDXL,
 
305
    .priv_data_size = sizeof(CDXLVideoContext),
 
306
    .init           = cdxl_decode_init,
 
307
    .close          = cdxl_decode_end,
 
308
    .decode         = cdxl_decode_frame,
 
309
    .capabilities   = CODEC_CAP_DR1,
 
310
    .long_name      = NULL_IF_CONFIG_SMALL("Commodore CDXL video"),
 
311
};