Coverage Report

Created: 2026-02-14 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/jvdec.c
Line
Count
Source
1
/*
2
 * Bitmap Brothers JV video decoder
3
 * Copyright (c) 2011 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
24
 * Bitmap Brothers JV video decoder
25
 * @author Peter Ross <pross@xvid.org>
26
 */
27
28
#include "libavutil/intreadwrite.h"
29
30
#include "avcodec.h"
31
#include "blockdsp.h"
32
#include "codec_internal.h"
33
#include "decode.h"
34
#include "get_bits.h"
35
36
typedef struct JvContext {
37
    BlockDSPContext bdsp;
38
    AVFrame   *frame;
39
    uint32_t   palette[AVPALETTE_COUNT];
40
} JvContext;
41
42
static av_cold int decode_init(AVCodecContext *avctx)
43
752
{
44
752
    JvContext *s = avctx->priv_data;
45
46
752
    if (!avctx->width || !avctx->height ||
47
615
        (avctx->width & 7) || (avctx->height & 7)) {
48
151
        av_log(avctx, AV_LOG_ERROR, "Invalid video dimensions: %dx%d\n",
49
151
               avctx->width, avctx->height);
50
151
        return AVERROR(EINVAL);
51
151
    }
52
53
601
    s->frame = av_frame_alloc();
54
601
    if (!s->frame)
55
0
        return AVERROR(ENOMEM);
56
57
601
    avctx->pix_fmt = AV_PIX_FMT_PAL8;
58
601
    ff_blockdsp_init(&s->bdsp);
59
601
    return 0;
60
601
}
61
62
/**
63
 * Decode 2x2 block
64
 */
65
static inline void decode2x2(GetBitContext *gb, uint8_t *dst, int linesize)
66
14.7M
{
67
14.7M
    int i, j, v[2];
68
69
14.7M
    switch (get_bits(gb, 2)) {
70
134k
    case 1:
71
134k
        v[0] = get_bits(gb, 8);
72
402k
        for (j = 0; j < 2; j++)
73
268k
            memset(dst + j * linesize, v[0], 2);
74
134k
        break;
75
154k
    case 2:
76
154k
        v[0] = get_bits(gb, 8);
77
154k
        v[1] = get_bits(gb, 8);
78
463k
        for (j = 0; j < 2; j++)
79
927k
            for (i = 0; i < 2; i++)
80
618k
                dst[j * linesize + i] = v[get_bits1(gb)];
81
154k
        break;
82
13.8M
    case 3:
83
41.6M
        for (j = 0; j < 2; j++)
84
83.3M
            for (i = 0; i < 2; i++)
85
55.5M
                dst[j * linesize + i] = get_bits(gb, 8);
86
14.7M
    }
87
14.7M
}
88
89
/**
90
 * Decode 4x4 block
91
 */
92
static inline void decode4x4(GetBitContext *gb, uint8_t *dst, int linesize)
93
4.92M
{
94
4.92M
    int i, j, v[2];
95
96
4.92M
    switch (get_bits(gb, 2)) {
97
155k
    case 1:
98
155k
        v[0] = get_bits(gb, 8);
99
779k
        for (j = 0; j < 4; j++)
100
623k
            memset(dst + j * linesize, v[0], 4);
101
155k
        break;
102
218k
    case 2:
103
218k
        v[0] = get_bits(gb, 8);
104
218k
        v[1] = get_bits(gb, 8);
105
656k
        for (j = 2; j >= 0; j -= 2) {
106
2.18M
            for (i = 0; i < 4; i++)
107
1.74M
                dst[j * linesize + i] = v[get_bits1(gb)];
108
2.18M
            for (i = 0; i < 4; i++)
109
1.74M
                dst[(j + 1) * linesize + i] = v[get_bits1(gb)];
110
437k
        }
111
218k
        break;
112
3.68M
    case 3:
113
11.0M
        for (j = 0; j < 4; j += 2)
114
22.1M
            for (i = 0; i < 4; i += 2)
115
14.7M
                decode2x2(gb, dst + j * linesize + i, linesize);
116
4.92M
    }
117
4.92M
}
118
119
/**
120
 * Decode 8x8 block
121
 */
122
static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize,
123
                             BlockDSPContext *bdsp)
124
16.6M
{
125
16.6M
    int i, j, v[2];
126
127
16.6M
    switch (get_bits(gb, 2)) {
128
1.56M
    case 1:
129
1.56M
        v[0] = get_bits(gb, 8);
130
1.56M
        bdsp->fill_block_tab[1](dst, v[0], linesize, 8);
131
1.56M
        break;
132
1.31M
    case 2:
133
1.31M
        v[0] = get_bits(gb, 8);
134
1.31M
        v[1] = get_bits(gb, 8);
135
11.8M
        for (j = 7; j >= 0; j--)
136
94.4M
            for (i = 0; i < 8; i++)
137
83.9M
                dst[j * linesize + i] = v[get_bits1(gb)];
138
1.31M
        break;
139
1.23M
    case 3:
140
3.69M
        for (j = 0; j < 8; j += 4)
141
7.38M
            for (i = 0; i < 8; i += 4)
142
4.92M
                decode4x4(gb, dst + j * linesize + i, linesize);
143
16.6M
    }
144
16.6M
}
145
146
static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
147
                        int *got_frame, AVPacket *avpkt)
148
294k
{
149
294k
    JvContext *s = avctx->priv_data;
150
294k
    const uint8_t *buf = avpkt->data;
151
294k
    const uint8_t *buf_end = buf + avpkt->size;
152
294k
    int video_size, video_type, i, j, ret;
153
154
294k
    if (avpkt->size < 6)
155
153k
        return AVERROR_INVALIDDATA;
156
157
141k
    video_size = AV_RL32(buf);
158
141k
    video_type = buf[4];
159
141k
    buf += 5;
160
161
141k
    if (video_size) {
162
137k
        if (video_size < 0 || video_size > avpkt->size - 5) {
163
8.19k
            av_log(avctx, AV_LOG_ERROR, "video size %d invalid\n", video_size);
164
8.19k
            return AVERROR_INVALIDDATA;
165
8.19k
        }
166
167
129k
        if (video_type == 0 || video_type == 1) {
168
123k
            GetBitContext gb;
169
123k
            init_get_bits(&gb, buf, 8 * video_size);
170
171
123k
            if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
172
0
                return ret;
173
174
123k
            if (avctx->height/8 * (avctx->width/8) > 4 * video_size) {
175
9.63k
                av_log(avctx, AV_LOG_ERROR, "Insufficient input data for dimensions\n");
176
9.63k
                return AVERROR_INVALIDDATA;
177
9.63k
            }
178
179
516k
            for (j = 0; j < avctx->height; j += 8)
180
17.0M
                for (i = 0; i < avctx->width; i += 8)
181
16.6M
                    decode8x8(&gb,
182
16.6M
                              s->frame->data[0] + j * s->frame->linesize[0] + i,
183
16.6M
                              s->frame->linesize[0], &s->bdsp);
184
185
113k
            buf += video_size;
186
113k
        } else if (video_type == 2) {
187
5.88k
            int v = *buf++;
188
189
5.88k
            av_frame_unref(s->frame);
190
5.88k
            if ((ret = ff_get_buffer(avctx, s->frame, AV_GET_BUFFER_FLAG_REF)) < 0)
191
0
                return ret;
192
193
380M
            for (j = 0; j < avctx->height; j++)
194
380M
                memset(s->frame->data[0] + j * s->frame->linesize[0],
195
380M
                       v, avctx->width);
196
5.88k
        } else {
197
546
            av_log(avctx, AV_LOG_WARNING,
198
546
                   "unsupported frame type %i\n", video_type);
199
546
            return AVERROR_INVALIDDATA;
200
546
        }
201
129k
    }
202
203
122k
    if (buf_end - buf >= AVPALETTE_COUNT * 3) {
204
482k
        for (i = 0; i < AVPALETTE_COUNT; i++) {
205
480k
            uint32_t pal = AV_RB24(buf);
206
480k
            s->palette[i] = 0xFFU << 24 | pal << 2 | ((pal >> 4) & 0x30303);
207
480k
            buf += 3;
208
480k
        }
209
1.87k
    }
210
211
122k
    if (video_size) {
212
119k
        memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
213
214
119k
        if ((ret = av_frame_ref(rframe, s->frame)) < 0)
215
0
            return ret;
216
119k
        *got_frame = 1;
217
119k
    }
218
219
122k
    return avpkt->size;
220
122k
}
221
222
static av_cold int decode_close(AVCodecContext *avctx)
223
601
{
224
601
    JvContext *s = avctx->priv_data;
225
226
601
    av_frame_free(&s->frame);
227
228
601
    return 0;
229
601
}
230
231
const FFCodec ff_jv_decoder = {
232
    .p.name         = "jv",
233
    CODEC_LONG_NAME("Bitmap Brothers JV video"),
234
    .p.type         = AVMEDIA_TYPE_VIDEO,
235
    .p.id           = AV_CODEC_ID_JV,
236
    .priv_data_size = sizeof(JvContext),
237
    .init           = decode_init,
238
    .close          = decode_close,
239
    FF_CODEC_DECODE_CB(decode_frame),
240
    .p.capabilities = AV_CODEC_CAP_DR1,
241
};