FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/mss1.c
Date: 2024-04-24 18:52:15
Exec Total Coverage
Lines: 104 112 92.9%
Functions: 11 11 100.0%
Branches: 26 34 76.5%

Line Branch Exec Source
1 /*
2 * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder
3 * Copyright (c) 2012 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 * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder
25 */
26
27 #include "avcodec.h"
28 #include "codec_internal.h"
29 #include "decode.h"
30 #include "mss12.h"
31
32 typedef struct MSS1Context {
33 MSS12Context ctx;
34 AVFrame *pic;
35 SliceContext sc;
36 } MSS1Context;
37
38 200964 static void arith_normalise(ArithCoder *c)
39 {
40 for (;;) {
41
2/2
✓ Branch 0 taken 261731 times.
✓ Branch 1 taken 29129 times.
290860 if (c->high >= 0x8000) {
42
2/2
✓ Branch 0 taken 231213 times.
✓ Branch 1 taken 30518 times.
261731 if (c->low < 0x8000) {
43
4/4
✓ Branch 0 taken 105671 times.
✓ Branch 1 taken 125542 times.
✓ Branch 2 taken 30249 times.
✓ Branch 3 taken 75422 times.
231213 if (c->low >= 0x4000 && c->high < 0xC000) {
44 30249 c->value -= 0x4000;
45 30249 c->low -= 0x4000;
46 30249 c->high -= 0x4000;
47 } else {
48 200964 return;
49 }
50 } else {
51 30518 c->value -= 0x8000;
52 30518 c->low -= 0x8000;
53 30518 c->high -= 0x8000;
54 }
55 }
56 89896 c->value <<= 1;
57 89896 c->low <<= 1;
58 89896 c->high <<= 1;
59 89896 c->high |= 1;
60
2/2
✓ Branch 1 taken 224 times.
✓ Branch 2 taken 89672 times.
89896 if (get_bits_left(c->gbc.gb) < 1)
61 224 c->overread++;
62 89896 c->value |= get_bits1(c->gbc.gb);
63 }
64 }
65
66
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
20 ARITH_GET_BIT(arith)
67
68 6 static int arith_get_bits(ArithCoder *c, int bits)
69 {
70 6 int range = c->high - c->low + 1;
71 6 int val = (((c->value - c->low + 1) << bits) - 1) / range;
72 6 int prob = range * val;
73
74 6 c->high = ((prob + range) >> bits) + c->low - 1;
75 6 c->low += prob >> bits;
76
77 6 arith_normalise(c);
78
79 6 return val;
80 }
81
82 409 static int arith_get_number(ArithCoder *c, int mod_val)
83 {
84 409 int range = c->high - c->low + 1;
85 409 int val = ((c->value - c->low + 1) * mod_val - 1) / range;
86 409 int prob = range * val;
87
88 409 c->high = (prob + range) / mod_val + c->low - 1;
89 409 c->low += prob / mod_val;
90
91 409 arith_normalise(c);
92
93 409 return val;
94 }
95
96 200529 static int arith_get_prob(ArithCoder *c, int16_t *probs)
97 {
98 200529 int range = c->high - c->low + 1;
99 200529 int val = ((c->value - c->low + 1) * probs[0] - 1) / range;
100 200529 int sym = 1;
101
102
2/2
✓ Branch 0 taken 82191 times.
✓ Branch 1 taken 200529 times.
282720 while (probs[sym] > val)
103 82191 sym++;
104
105 200529 c->high = range * probs[sym - 1] / probs[0] + c->low - 1;
106 200529 c->low += range * probs[sym] / probs[0];
107
108 200529 return sym;
109 }
110
111 200529 ARITH_GET_MODEL_SYM(arith)
112
113 20 static void arith_init(ArithCoder *c, GetBitContext *gb)
114 {
115 20 c->low = 0;
116 20 c->high = 0xFFFF;
117 20 c->value = get_bits(gb, 16);
118 20 c->overread = 0;
119 20 c->gbc.gb = gb;
120 20 c->get_model_sym = arith_get_model_sym;
121 20 c->get_number = arith_get_number;
122 20 }
123
124 2 static int decode_pal(MSS12Context *ctx, ArithCoder *acoder)
125 {
126 int i, ncol, r, g, b;
127 2 uint32_t *pal = ctx->pal + 256 - ctx->free_colours;
128
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!ctx->free_colours)
130 return 0;
131
132 2 ncol = arith_get_number(acoder, ctx->free_colours + 1);
133
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (i = 0; i < ncol; i++) {
134 2 r = arith_get_bits(acoder, 8);
135 2 g = arith_get_bits(acoder, 8);
136 2 b = arith_get_bits(acoder, 8);
137 2 *pal++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
138 }
139
140 2 return !!ncol;
141 }
142
143 20 static int mss1_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
144 int *got_frame, AVPacket *avpkt)
145 {
146 20 MSS1Context *ctx = avctx->priv_data;
147 20 MSS12Context *c = &ctx->ctx;
148 GetBitContext gb;
149 ArithCoder acoder;
150 20 int pal_changed = 0;
151 int ret;
152
153
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
154 return ret;
155
156 20 arith_init(&acoder, &gb);
157
158
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if ((ret = ff_reget_buffer(avctx, ctx->pic, 0)) < 0)
159 return ret;
160
161 20 c->pal_pic = ctx->pic->data[0] + ctx->pic->linesize[0] * (avctx->height - 1);
162 20 c->pal_stride = -ctx->pic->linesize[0];
163 20 c->keyframe = !arith_get_bit(&acoder);
164
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (c->keyframe) {
165 2 c->corrupted = 0;
166 2 ff_mss12_slicecontext_reset(&ctx->sc);
167 2 pal_changed = decode_pal(c, &acoder);
168 2 ctx->pic->flags |= AV_FRAME_FLAG_KEY;
169 2 ctx->pic->pict_type = AV_PICTURE_TYPE_I;
170 } else {
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (c->corrupted)
172 return AVERROR_INVALIDDATA;
173 18 ctx->pic->flags &= ~AV_FRAME_FLAG_KEY;
174 18 ctx->pic->pict_type = AV_PICTURE_TYPE_P;
175 }
176 20 c->corrupted = ff_mss12_decode_rect(&ctx->sc, &acoder, 0, 0,
177 avctx->width, avctx->height);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (c->corrupted)
179 return AVERROR_INVALIDDATA;
180 20 memcpy(ctx->pic->data[1], c->pal, AVPALETTE_SIZE);
181 #if FF_API_PALETTE_HAS_CHANGED
182 FF_DISABLE_DEPRECATION_WARNINGS
183 20 ctx->pic->palette_has_changed = pal_changed;
184 FF_ENABLE_DEPRECATION_WARNINGS
185 #endif
186
187
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if ((ret = av_frame_ref(rframe, ctx->pic)) < 0)
188 return ret;
189
190 20 *got_frame = 1;
191
192 /* always report that the buffer was completely consumed */
193 20 return avpkt->size;
194 }
195
196 2 static av_cold int mss1_decode_init(AVCodecContext *avctx)
197 {
198 2 MSS1Context * const c = avctx->priv_data;
199 int ret;
200
201 2 c->ctx.avctx = avctx;
202
203 2 c->pic = av_frame_alloc();
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!c->pic)
205 return AVERROR(ENOMEM);
206
207 2 ret = ff_mss12_decode_init(&c->ctx, 0, &c->sc, NULL);
208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
209 return ret;
210
211 2 avctx->pix_fmt = AV_PIX_FMT_PAL8;
212
213 2 return ret;
214 }
215
216 2 static av_cold int mss1_decode_end(AVCodecContext *avctx)
217 {
218 2 MSS1Context * const ctx = avctx->priv_data;
219
220 2 av_frame_free(&ctx->pic);
221 2 ff_mss12_decode_end(&ctx->ctx);
222
223 2 return 0;
224 }
225
226 const FFCodec ff_mss1_decoder = {
227 .p.name = "mss1",
228 CODEC_LONG_NAME("MS Screen 1"),
229 .p.type = AVMEDIA_TYPE_VIDEO,
230 .p.id = AV_CODEC_ID_MSS1,
231 .priv_data_size = sizeof(MSS1Context),
232 .init = mss1_decode_init,
233 .close = mss1_decode_end,
234 FF_CODEC_DECODE_CB(mss1_decode_frame),
235 .p.capabilities = AV_CODEC_CAP_DR1,
236 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
237 };
238