GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/loco.c Lines: 117 182 64.3 %
Date: 2019-11-18 18:00:01 Branches: 49 105 46.7 %

Line Branch Exec Source
1
/*
2
 * LOCO codec
3
 * Copyright (c) 2005 Konstantin Shishkov
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
24
 * LOCO codec.
25
 */
26
27
#include "avcodec.h"
28
#include "get_bits.h"
29
#include "golomb.h"
30
#include "internal.h"
31
#include "mathops.h"
32
33
enum LOCO_MODE {
34
    LOCO_UNKN  =  0,
35
    LOCO_CYUY2 = -1,
36
    LOCO_CRGB  = -2,
37
    LOCO_CRGBA = -3,
38
    LOCO_CYV12 = -4,
39
    LOCO_YUY2  =  1,
40
    LOCO_UYVY  =  2,
41
    LOCO_RGB   =  3,
42
    LOCO_RGBA  =  4,
43
    LOCO_YV12  =  5,
44
};
45
46
typedef struct LOCOContext {
47
    AVCodecContext *avctx;
48
    int lossy;
49
    enum LOCO_MODE mode;
50
} LOCOContext;
51
52
typedef struct RICEContext {
53
    GetBitContext gb;
54
    int save, run, run2; /* internal rice decoder state */
55
    int sum, count; /* sum and count for getting rice parameter */
56
    int lossy;
57
} RICEContext;
58
59
500785
static int loco_get_rice_param(RICEContext *r)
60
{
61
500785
    int cnt = 0;
62
500785
    int val = r->count;
63
64

2389200
    while (r->sum > val && cnt < 9) {
65
1888415
        val <<= 1;
66
1888415
        cnt++;
67
    }
68
69
500785
    return cnt;
70
}
71
72
505344
static inline void loco_update_rice_param(RICEContext *r, int val)
73
{
74
505344
    r->sum += val;
75
505344
    r->count++;
76
77
505344
    if (r->count == 16) {
78
63144
        r->sum   >>= 1;
79
63144
        r->count >>= 1;
80
    }
81
505344
}
82
83
505344
static inline int loco_get_rice(RICEContext *r)
84
{
85
    int v;
86
505344
    if (r->run > 0) { /* we have zero run */
87
4559
        r->run--;
88
4559
        loco_update_rice_param(r, 0);
89
4559
        return 0;
90
    }
91
500785
    if (get_bits_left(&r->gb) < 1)
92
        return INT_MIN;
93
500785
    v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0);
94
500785
    loco_update_rice_param(r, (v + 1) >> 1);
95
500785
    if (!v) {
96
49474
        if (r->save >= 0) {
97
2574
            r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0);
98
2574
            if (r->run > 1)
99
901
                r->save += r->run + 1;
100
            else
101
1673
                r->save -= 3;
102
        } else
103
46900
            r->run2++;
104
    } else {
105
451311
        v = ((v >> 1) + r->lossy) ^ -(v & 1);
106
451311
        if (r->run2 > 0) {
107
27417
            if (r->run2 > 2)
108
3721
                r->save += r->run2;
109
            else
110
23696
                r->save -= 3;
111
27417
            r->run2 = 0;
112
        }
113
    }
114
115
500785
    return v;
116
}
117
118
/* LOCO main predictor - LOCO-I/JPEG-LS predictor */
119
498348
static inline int loco_predict(uint8_t* data, int stride)
120
{
121
    int a, b, c;
122
123
498348
    a = data[-stride];
124
498348
    b = data[-1];
125
498348
    c = data[-stride - 1];
126
127
498348
    return mid_pred(a, a + b - c, b);
128
}
129
130
24
static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
131
                             int stride, const uint8_t *buf, int buf_size)
132
{
133
    RICEContext rc;
134
    int val;
135
    int ret;
136
    int i, j;
137
138
24
    if(buf_size<=0)
139
        return -1;
140
141
24
    if ((ret = init_get_bits8(&rc.gb, buf, buf_size)) < 0)
142
        return ret;
143
144
24
    rc.save  = 0;
145
24
    rc.run   = 0;
146
24
    rc.run2  = 0;
147
24
    rc.lossy = l->lossy;
148
149
24
    rc.sum   = 8;
150
24
    rc.count = 1;
151
152
    /* restore top left pixel */
153
24
    val     = loco_get_rice(&rc);
154
24
    data[0] = 128 + val;
155
    /* restore top line */
156
3948
    for (i = 1; i < width; i++) {
157
3924
        val = loco_get_rice(&rc);
158
3924
        if (val == INT_MIN)
159
           return AVERROR_INVALIDDATA;
160
3924
        data[i] = data[i - 1] + val;
161
    }
162
24
    data += stride;
163
3072
    for (j = 1; j < height; j++) {
164
        /* restore left column */
165
3048
        val = loco_get_rice(&rc);
166
3048
        if (val == INT_MIN)
167
           return AVERROR_INVALIDDATA;
168
3048
        data[0] = data[-stride] + val;
169
        /* restore all other pixels */
170
501396
        for (i = 1; i < width; i++) {
171
498348
            val = loco_get_rice(&rc);
172
498348
            if (val == INT_MIN)
173
                return -1;
174
498348
            data[i] = loco_predict(&data[i], stride) + val;
175
        }
176
3048
        data += stride;
177
    }
178
179
24
    return (get_bits_count(&rc.gb) + 7) >> 3;
180
}
181
182
static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride)
183
{
184
    int y;
185
186
    for (y=1; y<height; y++) {
187
        if (width>=y) {
188
            memmove(data + y*stride,
189
                    data + y*(stride + 1),
190
                    (width-y));
191
            if (y+1 < height)
192
                memmove(data + y*stride + (width-y),
193
                        data + (y+1)*stride, y);
194
        }
195
    }
196
}
197
198
8
static int decode_frame(AVCodecContext *avctx,
199
                        void *data, int *got_frame,
200
                        AVPacket *avpkt)
201
{
202
8
    LOCOContext * const l = avctx->priv_data;
203
8
    const uint8_t *buf    = avpkt->data;
204
8
    int buf_size          = avpkt->size;
205
8
    AVFrame * const p     = data;
206
    int decoded, ret;
207
208
8
    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
209
        return ret;
210
8
    p->key_frame = 1;
211
212
#define ADVANCE_BY_DECODED do { \
213
    if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \
214
    buf += decoded; buf_size -= decoded; \
215
} while(0)
216

8
    switch(l->mode) {
217
3
    case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
218
3
        decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
219
                                    p->linesize[0], buf, buf_size);
220

3
        ADVANCE_BY_DECODED;
221
3
        decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
222
                                    p->linesize[1], buf, buf_size);
223

3
        ADVANCE_BY_DECODED;
224
3
        decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
225
                                    p->linesize[2], buf, buf_size);
226
3
        break;
227
    case LOCO_CYV12: case LOCO_YV12:
228
        decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
229
                                    p->linesize[0], buf, buf_size);
230
        ADVANCE_BY_DECODED;
231
        decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
232
                                    p->linesize[2], buf, buf_size);
233
        ADVANCE_BY_DECODED;
234
        decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
235
                                    p->linesize[1], buf, buf_size);
236
        break;
237
5
    case LOCO_CRGB: case LOCO_RGB:
238
5
        decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
239
5
                                    -p->linesize[1], buf, buf_size);
240

5
        ADVANCE_BY_DECODED;
241
5
        decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
242
5
                                    -p->linesize[0], buf, buf_size);
243

5
        ADVANCE_BY_DECODED;
244
5
        decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
245
5
                                    -p->linesize[2], buf, buf_size);
246
5
        if (avctx->width & 1) {
247
            rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0]);
248
            rotate_faulty_loco(p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[1]);
249
            rotate_faulty_loco(p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[2]);
250
        }
251
5
        break;
252
    case LOCO_CRGBA:
253
    case LOCO_RGBA:
254
        decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
255
                                    -p->linesize[1], buf, buf_size);
256
        ADVANCE_BY_DECODED;
257
        decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
258
                                    -p->linesize[0], buf, buf_size);
259
        ADVANCE_BY_DECODED;
260
        decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
261
                                    -p->linesize[2], buf, buf_size);
262
        ADVANCE_BY_DECODED;
263
        decoded = loco_decode_plane(l, p->data[3] + p->linesize[3]*(avctx->height-1), avctx->width, avctx->height,
264
                                    -p->linesize[3], buf, buf_size);
265
        break;
266
    default:
267
        av_assert0(0);
268
    }
269
270

8
    if (decoded < 0 || decoded > buf_size)
271
        goto buf_too_small;
272
8
    buf_size -= decoded;
273
274
8
    *got_frame      = 1;
275
276
8
    return avpkt->size - buf_size;
277
buf_too_small:
278
    av_log(avctx, AV_LOG_ERROR, "Input data too small.\n");
279
    return AVERROR(EINVAL);
280
}
281
282
4
static av_cold int decode_init(AVCodecContext *avctx)
283
{
284
4
    LOCOContext * const l = avctx->priv_data;
285
    int version;
286
287
4
    l->avctx = avctx;
288
4
    if (avctx->extradata_size < 12) {
289
        av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
290
               avctx->extradata_size);
291
        return AVERROR_INVALIDDATA;
292
    }
293
4
    version = AV_RL32(avctx->extradata);
294
4
    switch (version) {
295
    case 1:
296
        l->lossy = 0;
297
        break;
298
4
    case 2:
299
4
        l->lossy = AV_RL32(avctx->extradata + 8);
300
4
        break;
301
    default:
302
        l->lossy = AV_RL32(avctx->extradata + 8);
303
        avpriv_request_sample(avctx, "LOCO codec version %i", version);
304
    }
305
306
4
    if (l->lossy > 65536U) {
307
        av_log(avctx, AV_LOG_ERROR, "lossy %i is too large\n", l->lossy);
308
        return AVERROR_INVALIDDATA;
309
    }
310
311
4
    l->mode = AV_RL32(avctx->extradata + 4);
312

4
    switch (l->mode) {
313
2
    case LOCO_CYUY2:
314
    case LOCO_YUY2:
315
    case LOCO_UYVY:
316
2
        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
317
2
        break;
318
2
    case LOCO_CRGB:
319
    case LOCO_RGB:
320
2
        avctx->pix_fmt = AV_PIX_FMT_GBRP;
321
2
        break;
322
    case LOCO_CYV12:
323
    case LOCO_YV12:
324
        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
325
        break;
326
    case LOCO_CRGBA:
327
    case LOCO_RGBA:
328
        avctx->pix_fmt = AV_PIX_FMT_GBRAP;
329
        break;
330
    default:
331
        av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
332
        return AVERROR_INVALIDDATA;
333
    }
334
4
    if (avctx->debug & FF_DEBUG_PICT_INFO)
335
        av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
336
337
4
    return 0;
338
}
339
340
AVCodec ff_loco_decoder = {
341
    .name           = "loco",
342
    .long_name      = NULL_IF_CONFIG_SMALL("LOCO"),
343
    .type           = AVMEDIA_TYPE_VIDEO,
344
    .id             = AV_CODEC_ID_LOCO,
345
    .priv_data_size = sizeof(LOCOContext),
346
    .init           = decode_init,
347
    .decode         = decode_frame,
348
    .capabilities   = AV_CODEC_CAP_DR1,
349
};