~ubuntu-branches/ubuntu/saucy/gst-libav1.0/saucy-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libavcodec/targa.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-07-30 09:00:15 UTC
  • mfrom: (1.1.16) (7.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130730090015-sc1ou2yssu7q5w4e
Tags: 1.1.3-1
* New upstream development snapshot:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.1.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include "libavutil/imgutils.h"
24
24
#include "avcodec.h"
25
25
#include "bytestream.h"
 
26
#include "internal.h"
26
27
#include "targa.h"
27
28
 
28
29
typedef struct TargaContext {
29
30
    AVFrame picture;
 
31
    GetByteContext gb;
30
32
 
31
 
    int width, height;
32
 
    int bpp;
33
33
    int color_type;
34
34
    int compression_type;
35
35
} TargaContext;
36
36
 
37
 
#define CHECK_BUFFER_SIZE(buf, buf_end, needed, where) \
38
 
    if(needed > buf_end - buf){ \
39
 
        av_log(avctx, AV_LOG_ERROR, "Problem: unexpected end of data while reading " where "\n"); \
40
 
        return -1; \
41
 
    } \
42
 
 
43
 
static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s, const uint8_t *src, int src_size, uint8_t *dst, int w, int h, int stride, int bpp)
 
37
static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s,
 
38
                            uint8_t *dst, int w, int h, int stride, int bpp)
44
39
{
45
 
    int i, x, y;
 
40
    int x, y;
46
41
    int depth = (bpp + 1) >> 3;
47
42
    int type, count;
48
43
    int diff;
49
 
    const uint8_t *src_end = src + src_size;
50
44
 
51
45
    diff = stride - w * depth;
52
46
    x = y = 0;
53
 
    while(y < h){
54
 
        CHECK_BUFFER_SIZE(src, src_end, 1, "image type");
55
 
        type = *src++;
 
47
    while (y < h) {
 
48
        if (bytestream2_get_bytes_left(&s->gb) <= 0) {
 
49
            av_log(avctx, AV_LOG_ERROR,
 
50
                   "Ran ouf of data before end-of-image\n");
 
51
            return AVERROR_INVALIDDATA;
 
52
        }
 
53
        type  = bytestream2_get_byteu(&s->gb);
56
54
        count = (type & 0x7F) + 1;
57
55
        type &= 0x80;
58
 
        if((x + count > w) && (x + count + 1 > (h - y) * w)){
59
 
            av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count);
60
 
            return -1;
61
 
        }
62
 
        if(type){
63
 
            CHECK_BUFFER_SIZE(src, src_end, depth, "image data");
64
 
        }else{
65
 
            CHECK_BUFFER_SIZE(src, src_end, count * depth, "image data");
66
 
        }
67
 
        for(i = 0; i < count; i++){
68
 
            switch(depth){
69
 
            case 1:
70
 
                *dst = *src;
71
 
                break;
72
 
            case 2:
73
 
                *((uint16_t*)dst) = AV_RL16(src);
74
 
                break;
75
 
            case 3:
76
 
                dst[0] = src[0];
77
 
                dst[1] = src[1];
78
 
                dst[2] = src[2];
79
 
                break;
80
 
            case 4:
81
 
                *((uint32_t*)dst) = AV_RL32(src);
82
 
                break;
83
 
            }
84
 
            dst += depth;
85
 
            if(!type)
86
 
                src += depth;
87
 
 
88
 
            x++;
89
 
            if(x == w){
90
 
                x = 0;
91
 
                y++;
92
 
                dst += diff;
93
 
            }
94
 
        }
95
 
        if(type)
96
 
            src += depth;
 
56
        if (x + count > w && x + count + 1 > (h - y) * w) {
 
57
            av_log(avctx, AV_LOG_ERROR,
 
58
                   "Packet went out of bounds: position (%i,%i) size %i\n",
 
59
                   x, y, count);
 
60
            return AVERROR_INVALIDDATA;
 
61
        }
 
62
        if (!type) {
 
63
            do {
 
64
                int n  = FFMIN(count, w - x);
 
65
                bytestream2_get_buffer(&s->gb, dst, n * depth);
 
66
                count -= n;
 
67
                dst   += n * depth;
 
68
                x     += n;
 
69
                if (x == w) {
 
70
                    x    = 0;
 
71
                    y++;
 
72
                    dst += diff;
 
73
                }
 
74
            } while (count > 0);
 
75
        } else {
 
76
            uint8_t tmp[4];
 
77
            bytestream2_get_buffer(&s->gb, tmp, depth);
 
78
            do {
 
79
                int n  = FFMIN(count, w - x);
 
80
                count -= n;
 
81
                x     += n;
 
82
                do {
 
83
                    memcpy(dst, tmp, depth);
 
84
                    dst += depth;
 
85
                } while (--n);
 
86
                if (x == w) {
 
87
                    x    = 0;
 
88
                    y++;
 
89
                    dst += diff;
 
90
                }
 
91
            } while (count > 0);
 
92
        }
97
93
    }
98
 
    return src_size;
 
94
    return 0;
99
95
}
100
96
 
101
97
static int decode_frame(AVCodecContext *avctx,
102
 
                        void *data, int *data_size,
 
98
                        void *data, int *got_frame,
103
99
                        AVPacket *avpkt)
104
100
{
105
 
    const uint8_t *buf = avpkt->data;
106
 
    const uint8_t *buf_end = avpkt->data + avpkt->size;
107
101
    TargaContext * const s = avctx->priv_data;
108
102
    AVFrame *picture = data;
109
 
    AVFrame * const p= (AVFrame*)&s->picture;
 
103
    AVFrame * const p = &s->picture;
110
104
    uint8_t *dst;
111
105
    int stride;
112
106
    int idlen, compr, y, w, h, bpp, flags;
113
107
    int first_clr, colors, csize;
114
108
 
 
109
    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
 
110
 
115
111
    /* parse image header */
116
 
    CHECK_BUFFER_SIZE(buf, buf_end, 18, "header");
117
 
    idlen = *buf++;
118
 
    buf++; /* pal */
119
 
    compr = *buf++;
120
 
    first_clr = AV_RL16(buf); buf += 2;
121
 
    colors = AV_RL16(buf); buf += 2;
122
 
    csize = *buf++;
123
 
    buf += 2; /* x */
124
 
    y = AV_RL16(buf); buf += 2;
125
 
    w = AV_RL16(buf); buf += 2;
126
 
    h = AV_RL16(buf); buf += 2;
127
 
    bpp = *buf++;
128
 
    flags = *buf++;
129
 
    //skip identifier if any
130
 
    CHECK_BUFFER_SIZE(buf, buf_end, idlen, "identifiers");
131
 
    buf += idlen;
132
 
    s->bpp = bpp;
133
 
    s->width = w;
134
 
    s->height = h;
135
 
    switch(s->bpp){
 
112
    idlen     = bytestream2_get_byte(&s->gb);
 
113
    bytestream2_skip(&s->gb, 1); /* pal */
 
114
    compr     = bytestream2_get_byte(&s->gb);
 
115
    first_clr = bytestream2_get_le16(&s->gb);
 
116
    colors    = bytestream2_get_le16(&s->gb);
 
117
    csize     = bytestream2_get_byte(&s->gb);
 
118
    bytestream2_skip(&s->gb, 4); /* 2: x, 2: y */
 
119
    w         = bytestream2_get_le16(&s->gb);
 
120
    h         = bytestream2_get_le16(&s->gb);
 
121
    bpp       = bytestream2_get_byte(&s->gb);
 
122
    flags     = bytestream2_get_byte(&s->gb);
 
123
    // skip identifier if any
 
124
    bytestream2_skip(&s->gb, idlen);
 
125
 
 
126
    switch(bpp){
136
127
    case 8:
137
 
        avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? PIX_FMT_GRAY8 : PIX_FMT_PAL8;
 
128
        avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? AV_PIX_FMT_GRAY8 : AV_PIX_FMT_PAL8;
138
129
        break;
139
130
    case 15:
140
 
        avctx->pix_fmt = PIX_FMT_RGB555;
 
131
        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
141
132
        break;
142
133
    case 16:
143
 
        avctx->pix_fmt = PIX_FMT_RGB555;
 
134
        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
144
135
        break;
145
136
    case 24:
146
 
        avctx->pix_fmt = PIX_FMT_BGR24;
 
137
        avctx->pix_fmt = AV_PIX_FMT_BGR24;
147
138
        break;
148
139
    case 32:
149
 
        avctx->pix_fmt = PIX_FMT_RGB32;
 
140
        avctx->pix_fmt = AV_PIX_FMT_BGRA;
150
141
        break;
151
142
    default:
152
 
        av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", s->bpp);
 
143
        av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", bpp);
153
144
        return -1;
154
145
    }
155
146
 
160
151
        return -1;
161
152
    if(w != avctx->width || h != avctx->height)
162
153
        avcodec_set_dimensions(avctx, w, h);
163
 
    if(avctx->get_buffer(avctx, p) < 0){
 
154
    if(ff_get_buffer(avctx, p) < 0){
164
155
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
165
156
        return -1;
166
157
    }
187
178
            return -1;
188
179
        }
189
180
        pal_size = colors * pal_sample_size;
190
 
        CHECK_BUFFER_SIZE(buf, buf_end, pal_size, "color table");
191
 
        if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway
192
 
            buf += pal_size;
 
181
        if(avctx->pix_fmt != AV_PIX_FMT_PAL8)//should not occur but skip palette anyway
 
182
            bytestream2_skip(&s->gb, pal_size);
193
183
        else{
194
184
            int t;
195
185
            uint32_t *pal = ((uint32_t *)p->data[1]) + first_clr;
196
186
 
 
187
            if (bytestream2_get_bytes_left(&s->gb) < pal_size) {
 
188
                av_log(avctx, AV_LOG_ERROR,
 
189
                       "Not enough data to read palette\n");
 
190
                return AVERROR_INVALIDDATA;
 
191
            }
197
192
            switch (pal_sample_size) {
198
193
            case 3:
199
194
                /* RGB24 */
200
195
                for (t = 0; t < colors; t++)
201
 
                    *pal++ = bytestream_get_le24(&buf);
 
196
                    *pal++ = bytestream2_get_le24u(&s->gb);
202
197
                break;
203
198
            case 2:
204
199
                /* RGB555 */
205
200
                for (t = 0; t < colors; t++) {
206
 
                    uint32_t v = bytestream_get_le16(&buf);
 
201
                    uint32_t v = bytestream2_get_le16u(&s->gb);
207
202
                    v = ((v & 0x7C00) <<  9) |
208
203
                        ((v & 0x03E0) <<  6) |
209
204
                        ((v & 0x001F) <<  3);
216
211
            p->palette_has_changed = 1;
217
212
        }
218
213
    }
219
 
    if((compr & (~TGA_RLE)) == TGA_NODATA)
220
 
        memset(p->data[0], 0, p->linesize[0] * s->height);
221
 
    else{
 
214
    if ((compr & (~TGA_RLE)) == TGA_NODATA) {
 
215
        memset(p->data[0], 0, p->linesize[0] * h);
 
216
    } else {
222
217
        if(compr & TGA_RLE){
223
 
            int res = targa_decode_rle(avctx, s, buf, buf_end - buf, dst, avctx->width, avctx->height, stride, bpp);
 
218
            int res = targa_decode_rle(avctx, s, dst, w, h, stride, bpp);
224
219
            if (res < 0)
225
 
                return -1;
226
 
            buf += res;
227
 
        }else{
228
 
            size_t img_size = s->width * ((s->bpp + 1) >> 3);
229
 
            CHECK_BUFFER_SIZE(buf, buf_end, img_size, "image data");
230
 
            for(y = 0; y < s->height; y++){
231
 
#if HAVE_BIGENDIAN
232
 
                int x;
233
 
                if((s->bpp + 1) >> 3 == 2){
234
 
                    uint16_t *dst16 = (uint16_t*)dst;
235
 
                    for(x = 0; x < s->width; x++)
236
 
                        dst16[x] = AV_RL16(buf + x * 2);
237
 
                }else if((s->bpp + 1) >> 3 == 4){
238
 
                    uint32_t *dst32 = (uint32_t*)dst;
239
 
                    for(x = 0; x < s->width; x++)
240
 
                        dst32[x] = AV_RL32(buf + x * 4);
241
 
                }else
242
 
#endif
243
 
                    memcpy(dst, buf, img_size);
244
 
 
 
220
                return res;
 
221
        } else {
 
222
            size_t img_size = w * ((bpp + 1) >> 3);
 
223
            if (bytestream2_get_bytes_left(&s->gb) < img_size * h) {
 
224
                av_log(avctx, AV_LOG_ERROR,
 
225
                       "Not enough data available for image\n");
 
226
                return AVERROR_INVALIDDATA;
 
227
            }
 
228
            for (y = 0; y < h; y++) {
 
229
                bytestream2_get_bufferu(&s->gb, dst, img_size);
245
230
                dst += stride;
246
 
                buf += img_size;
247
231
            }
248
232
        }
249
233
    }
250
234
 
251
 
    *picture= *(AVFrame*)&s->picture;
252
 
    *data_size = sizeof(AVPicture);
 
235
    *picture   = s->picture;
 
236
    *got_frame = 1;
253
237
 
254
238
    return avpkt->size;
255
239
}
257
241
static av_cold int targa_init(AVCodecContext *avctx){
258
242
    TargaContext *s = avctx->priv_data;
259
243
 
260
 
    avcodec_get_frame_defaults((AVFrame*)&s->picture);
261
 
    avctx->coded_frame= (AVFrame*)&s->picture;
 
244
    avcodec_get_frame_defaults(&s->picture);
 
245
    avctx->coded_frame = &s->picture;
262
246
 
263
247
    return 0;
264
248
}
275
259
AVCodec ff_targa_decoder = {
276
260
    .name           = "targa",
277
261
    .type           = AVMEDIA_TYPE_VIDEO,
278
 
    .id             = CODEC_ID_TARGA,
 
262
    .id             = AV_CODEC_ID_TARGA,
279
263
    .priv_data_size = sizeof(TargaContext),
280
264
    .init           = targa_init,
281
265
    .close          = targa_end,
282
266
    .decode         = decode_frame,
283
267
    .capabilities   = CODEC_CAP_DR1,
284
 
    .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"),
 
268
    .long_name      = NULL_IF_CONFIG_SMALL("Truevision Targa image"),
285
269
};