GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/roqvideodec.c Lines: 133 143 93.0 %
Date: 2020-08-14 10:39:37 Branches: 61 74 82.4 %

Line Branch Exec Source
1
/*
2
 * Copyright (C) 2003 The FFmpeg project
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
/**
22
 * @file
23
 * id RoQ Video Decoder by Dr. Tim Ferguson
24
 * For more information about the id RoQ format, visit:
25
 *   http://www.csse.monash.edu.au/~timf/
26
 */
27
28
#include "libavutil/avassert.h"
29
#include "libavutil/imgutils.h"
30
31
#include "avcodec.h"
32
#include "bytestream.h"
33
#include "internal.h"
34
#include "roqvideo.h"
35
36
225
static void roqvideo_decode_frame(RoqContext *ri)
37
{
38
225
    unsigned int chunk_id = 0, chunk_arg = 0;
39
225
    unsigned long chunk_size = 0;
40
225
    int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
41
    int vqid, xpos, ypos, xp, yp, x, y, mx, my;
42
225
    int frame_stats[2][4] = {{0},{0}};
43
    roq_qcell *qcell;
44
    int64_t chunk_start;
45
46
428
    while (bytestream2_get_bytes_left(&ri->gb) >= 8) {
47
428
        chunk_id   = bytestream2_get_le16(&ri->gb);
48
428
        chunk_size = bytestream2_get_le32(&ri->gb);
49
428
        chunk_arg  = bytestream2_get_le16(&ri->gb);
50
51
428
        if(chunk_id == RoQ_QUAD_VQ)
52
225
            break;
53
203
        if(chunk_id == RoQ_QUAD_CODEBOOK) {
54
203
            if((nv1 = chunk_arg >> 8) == 0)
55
67
                nv1 = 256;
56

203
            if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
57
1
                nv2 = 256;
58
51102
            for(i = 0; i < nv1; i++) {
59
50899
                ri->cb2x2[i].y[0] = bytestream2_get_byte(&ri->gb);
60
50899
                ri->cb2x2[i].y[1] = bytestream2_get_byte(&ri->gb);
61
50899
                ri->cb2x2[i].y[2] = bytestream2_get_byte(&ri->gb);
62
50899
                ri->cb2x2[i].y[3] = bytestream2_get_byte(&ri->gb);
63
50899
                ri->cb2x2[i].u    = bytestream2_get_byte(&ri->gb);
64
50899
                ri->cb2x2[i].v    = bytestream2_get_byte(&ri->gb);
65
            }
66
17934
            for(i = 0; i < nv2; i++)
67
88655
                for(j = 0; j < 4; j++)
68
70924
                    ri->cb4x4[i].idx[j] = bytestream2_get_byte(&ri->gb);
69
        }
70
    }
71
72
225
    chunk_start = bytestream2_tell(&ri->gb);
73
225
    xpos = ypos = 0;
74
75
225
    if (chunk_size > bytestream2_get_bytes_left(&ri->gb)) {
76
        av_log(ri->avctx, AV_LOG_ERROR, "Chunk does not fit in input buffer\n");
77
        chunk_size = bytestream2_get_bytes_left(&ri->gb);
78
    }
79
80
113460
    while (bytestream2_tell(&ri->gb) < chunk_start + chunk_size) {
81
340342
        for (yp = ypos; yp < ypos + 16; yp += 8)
82
680707
            for (xp = xpos; xp < xpos + 16; xp += 8) {
83
453825
                if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) {
84
4
                    av_log(ri->avctx, AV_LOG_VERBOSE, "Chunk is too short\n");
85
34
                    return;
86
                }
87
453821
                if (vqflg_pos < 0) {
88
56771
                    vqflg = bytestream2_get_le16(&ri->gb);
89
56771
                    vqflg_pos = 7;
90
                }
91
453821
                vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
92
453821
                frame_stats[0][vqid]++;
93
453821
                vqflg_pos--;
94
95

453821
                switch(vqid) {
96
121738
                case RoQ_ID_MOT:
97
121738
                    break;
98
9277
                case RoQ_ID_FCC: {
99
9277
                    int byte = bytestream2_get_byte(&ri->gb);
100
9277
                    mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
101
9277
                    my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
102
9277
                    ff_apply_motion_8x8(ri, xp, yp, mx, my);
103
9277
                    break;
104
                }
105
7001
                case RoQ_ID_SLD:
106
7001
                    qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
107
7001
                    ff_apply_vector_4x4(ri, xp,     yp,     ri->cb2x2 + qcell->idx[0]);
108
7001
                    ff_apply_vector_4x4(ri, xp + 4, yp,     ri->cb2x2 + qcell->idx[1]);
109
7001
                    ff_apply_vector_4x4(ri, xp,     yp + 4, ri->cb2x2 + qcell->idx[2]);
110
7001
                    ff_apply_vector_4x4(ri, xp + 4, yp + 4, ri->cb2x2 + qcell->idx[3]);
111
7001
                    break;
112
315805
                case RoQ_ID_CCC:
113
1578984
                    for (k = 0; k < 4; k++) {
114
1263209
                        x = xp; y = yp;
115
1263209
                        if(k & 0x01) x += 4;
116
1263209
                        if(k & 0x02) y += 4;
117
118
1263209
                        if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) {
119
30
                            av_log(ri->avctx, AV_LOG_VERBOSE, "Chunk is too short\n");
120
30
                            return;
121
                        }
122
1263179
                        if (vqflg_pos < 0) {
123
157911
                            vqflg = bytestream2_get_le16(&ri->gb);
124
157911
                            vqflg_pos = 7;
125
                        }
126
1263179
                        vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
127
1263179
                        frame_stats[1][vqid]++;
128

1263179
                        vqflg_pos--;
129
                        switch(vqid) {
130
259115
                        case RoQ_ID_MOT:
131
259115
                            break;
132
521989
                        case RoQ_ID_FCC: {
133
521989
                            int byte = bytestream2_get_byte(&ri->gb);
134
521989
                            mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
135
521989
                            my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
136
521989
                            ff_apply_motion_4x4(ri, x, y, mx, my);
137
521989
                            break;
138
                        }
139
116817
                        case RoQ_ID_SLD:
140
116817
                            qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
141
116817
                            ff_apply_vector_2x2(ri, x,     y,     ri->cb2x2 + qcell->idx[0]);
142
116817
                            ff_apply_vector_2x2(ri, x + 2, y,     ri->cb2x2 + qcell->idx[1]);
143
116817
                            ff_apply_vector_2x2(ri, x,     y + 2, ri->cb2x2 + qcell->idx[2]);
144
116817
                            ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + qcell->idx[3]);
145
116817
                            break;
146
365258
                        case RoQ_ID_CCC:
147
365258
                            ff_apply_vector_2x2(ri, x,     y,     ri->cb2x2 + bytestream2_get_byte(&ri->gb));
148
365258
                            ff_apply_vector_2x2(ri, x + 2, y,     ri->cb2x2 + bytestream2_get_byte(&ri->gb));
149
365258
                            ff_apply_vector_2x2(ri, x,     y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
150
365258
                            ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
151
365258
                            break;
152
                        }
153
1263179
                    }
154
315775
                    break;
155
453791
                default:
156
                    av_assert2(0);
157
            }
158
        }
159
160
113426
        xpos += 16;
161
113426
        if (xpos >= ri->width) {
162
3596
            xpos -= ri->width;
163
3596
            ypos += 16;
164
        }
165
113426
        if(ypos >= ri->height)
166
191
            break;
167
    }
168
}
169
170
171
10
static av_cold int roq_decode_init(AVCodecContext *avctx)
172
{
173
10
    RoqContext *s = avctx->priv_data;
174
175
10
    s->avctx = avctx;
176
177

10
    if (avctx->width % 16 || avctx->height % 16) {
178
        avpriv_request_sample(avctx, "Dimensions not being a multiple of 16");
179
        return AVERROR_PATCHWELCOME;
180
    }
181
182
10
    s->width = avctx->width;
183
10
    s->height = avctx->height;
184
185
10
    s->last_frame    = av_frame_alloc();
186
10
    s->current_frame = av_frame_alloc();
187

10
    if (!s->current_frame || !s->last_frame) {
188
        av_frame_free(&s->current_frame);
189
        av_frame_free(&s->last_frame);
190
        return AVERROR(ENOMEM);
191
    }
192
193
10
    avctx->pix_fmt = AV_PIX_FMT_YUVJ444P;
194
10
    avctx->color_range = AVCOL_RANGE_JPEG;
195
196
10
    return 0;
197
}
198
199
225
static int roq_decode_frame(AVCodecContext *avctx,
200
                            void *data, int *got_frame,
201
                            AVPacket *avpkt)
202
{
203
225
    const uint8_t *buf = avpkt->data;
204
225
    int buf_size = avpkt->size;
205
225
    RoqContext *s = avctx->priv_data;
206

225
    int copy = !s->current_frame->data[0] && s->last_frame->data[0];
207
    int ret;
208
209
225
    if ((ret = ff_reget_buffer(avctx, s->current_frame, 0)) < 0)
210
        return ret;
211
212
225
    if (copy) {
213
4
        ret = av_frame_copy(s->current_frame, s->last_frame);
214
4
        if (ret < 0)
215
            return ret;
216
    }
217
218
225
    bytestream2_init(&s->gb, buf, buf_size);
219
225
    roqvideo_decode_frame(s);
220
221
225
    if ((ret = av_frame_ref(data, s->current_frame)) < 0)
222
        return ret;
223
225
    *got_frame      = 1;
224
225
    /* shuffle frames */
226
225
    FFSWAP(AVFrame *, s->current_frame, s->last_frame);
227
228
225
    return buf_size;
229
}
230
231
10
static av_cold int roq_decode_end(AVCodecContext *avctx)
232
{
233
10
    RoqContext *s = avctx->priv_data;
234
235
10
    av_frame_free(&s->current_frame);
236
10
    av_frame_free(&s->last_frame);
237
238
10
    return 0;
239
}
240
241
AVCodec ff_roq_decoder = {
242
    .name           = "roqvideo",
243
    .long_name      = NULL_IF_CONFIG_SMALL("id RoQ video"),
244
    .type           = AVMEDIA_TYPE_VIDEO,
245
    .id             = AV_CODEC_ID_ROQ,
246
    .priv_data_size = sizeof(RoqContext),
247
    .init           = roq_decode_init,
248
    .close          = roq_decode_end,
249
    .decode         = roq_decode_frame,
250
    .capabilities   = AV_CODEC_CAP_DR1,
251
};