FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/sunrastenc.c
Date: 2024-04-19 17:50:32
Exec Total Coverage
Lines: 71 98 72.4%
Functions: 4 4 100.0%
Branches: 28 51 54.9%

Line Branch Exec Source
1 /*
2 * Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image encoder
3 * Copyright (c) 2012 Aneesh Dogra (lionaneesh) <lionaneesh@gmail.com>
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 #include "libavutil/opt.h"
23
24 #include "avcodec.h"
25 #include "bytestream.h"
26 #include "codec_internal.h"
27 #include "encode.h"
28 #include "sunrast.h"
29
30 typedef struct SUNRASTContext {
31 AVClass *class;
32
33 PutByteContext p;
34 int depth; ///< depth of pixel
35 int length; ///< length (bytes) of image
36 int type; ///< type of file
37 int maptype; ///< type of colormap
38 int maplength; ///< length (bytes) of colormap
39 int size;
40 } SUNRASTContext;
41
42 13 static void sunrast_image_write_header(AVCodecContext *avctx)
43 {
44 13 SUNRASTContext *s = avctx->priv_data;
45
46 13 bytestream2_put_be32u(&s->p, RAS_MAGIC);
47 13 bytestream2_put_be32u(&s->p, avctx->width);
48 13 bytestream2_put_be32u(&s->p, avctx->height);
49 13 bytestream2_put_be32u(&s->p, s->depth);
50 13 bytestream2_put_be32u(&s->p, s->length);
51 13 bytestream2_put_be32u(&s->p, s->type);
52 13 bytestream2_put_be32u(&s->p, s->maptype);
53 13 bytestream2_put_be32u(&s->p, s->maplength);
54 13 }
55
56 13 static void sunrast_image_write_image(AVCodecContext *avctx,
57 const uint8_t *pixels,
58 const uint32_t *palette_data,
59 int linesize)
60 {
61 13 SUNRASTContext *s = avctx->priv_data;
62 const uint8_t *ptr;
63 int len, alen, x, y;
64
65
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (s->maplength) { // palettized
66 PutByteContext pb_r, pb_g;
67 int len = s->maplength / 3;
68
69 pb_r = s->p;
70 bytestream2_skip_p(&s->p, len);
71 pb_g = s->p;
72 bytestream2_skip_p(&s->p, len);
73
74 for (x = 0; x < len; x++) {
75 uint32_t pixel = palette_data[x];
76
77 bytestream2_put_byteu(&pb_r, (pixel >> 16) & 0xFF);
78 bytestream2_put_byteu(&pb_g, (pixel >> 8) & 0xFF);
79 bytestream2_put_byteu(&s->p, pixel & 0xFF);
80 }
81 }
82
83 13 len = (s->depth * avctx->width + 7) >> 3;
84 13 alen = len + (len & 1);
85 13 ptr = pixels;
86
87
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (s->type == RT_BYTE_ENCODED) {
88 uint8_t value, value2;
89 int run;
90
91 13 ptr = pixels;
92
93 #define GET_VALUE y >= avctx->height ? 0 : x >= len ? ptr[len-1] : ptr[x]
94
95 13 x = 0, y = 0;
96
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 value2 = GET_VALUE;
97
2/2
✓ Branch 0 taken 3917834 times.
✓ Branch 1 taken 13 times.
3917847 while (y < avctx->height) {
98 3917834 run = 1;
99 3917834 value = value2;
100 3917834 x++;
101
2/2
✓ Branch 0 taken 3718 times.
✓ Branch 1 taken 3914116 times.
3917834 if (x >= alen) {
102 3718 x = 0;
103 3718 ptr += linesize, y++;
104 }
105
106
3/4
✓ Branch 0 taken 3917821 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3917821 times.
3917834 value2 = GET_VALUE;
107
4/6
✓ Branch 0 taken 35830 times.
✓ Branch 1 taken 3917834 times.
✓ Branch 2 taken 35830 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35830 times.
✗ Branch 5 not taken.
3953664 while (value2 == value && run < 256 && y < avctx->height) {
108 35830 x++;
109 35830 run++;
110
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 35804 times.
35830 if (x >= alen) {
111 26 x = 0;
112 26 ptr += linesize, y++;
113 }
114
2/4
✓ Branch 0 taken 35830 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35830 times.
35830 value2 = GET_VALUE;
115 }
116
117
3/4
✓ Branch 0 taken 3916438 times.
✓ Branch 1 taken 1396 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3916438 times.
3917834 if (run > 2 || value == RLE_TRIGGER) {
118 1396 bytestream2_put_byteu(&s->p, RLE_TRIGGER);
119 1396 bytestream2_put_byteu(&s->p, run - 1);
120
1/2
✓ Branch 0 taken 1396 times.
✗ Branch 1 not taken.
1396 if (run > 1)
121 1396 bytestream2_put_byteu(&s->p, value);
122
2/2
✓ Branch 0 taken 3883890 times.
✓ Branch 1 taken 32548 times.
3916438 } else if (run == 1) {
123 3883890 bytestream2_put_byteu(&s->p, value);
124 } else
125 32548 bytestream2_put_be16u(&s->p, (value << 8) | value);
126 }
127
128 // update data length for header
129 13 s->length = bytestream2_tell_p(&s->p) - 32 - s->maplength;
130 } else {
131 for (y = 0; y < avctx->height; y++) {
132 bytestream2_put_buffer(&s->p, ptr, len);
133 if (len < alen)
134 bytestream2_put_byteu(&s->p, 0);
135 ptr += linesize;
136 }
137 }
138 13 }
139
140 1 static av_cold int sunrast_encode_init(AVCodecContext *avctx)
141 {
142 1 SUNRASTContext *s = avctx->priv_data;
143
144 // adjust boolean option to RT equivalent
145 1 s->type++;
146
147 1 s->maptype = RMT_NONE;
148 1 s->maplength = 0;
149
150
1/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 switch (avctx->pix_fmt) {
151 case AV_PIX_FMT_MONOWHITE:
152 s->depth = 1;
153 break;
154 case AV_PIX_FMT_PAL8 :
155 s->maptype = RMT_EQUAL_RGB;
156 s->maplength = 3 * 256;
157 /* fall-through */
158 case AV_PIX_FMT_GRAY8:
159 s->depth = 8;
160 break;
161 1 case AV_PIX_FMT_BGR24:
162 1 s->depth = 24;
163 1 break;
164 default:
165 return AVERROR_BUG;
166 }
167 1 s->length = avctx->height * (FFALIGN(avctx->width * s->depth, 16) >> 3);
168 1 s->size = 32 + s->maplength + s->length * s->type;
169
170 1 return 0;
171 }
172
173 13 static int sunrast_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
174 const AVFrame *frame, int *got_packet_ptr)
175 {
176 13 SUNRASTContext *s = avctx->priv_data;
177 int ret;
178
179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if ((ret = ff_alloc_packet(avctx, avpkt, s->size)) < 0)
180 return ret;
181
182 13 bytestream2_init_writer(&s->p, avpkt->data, avpkt->size);
183 13 sunrast_image_write_header(avctx);
184 13 sunrast_image_write_image(avctx, frame->data[0],
185 13 (const uint32_t *)frame->data[1],
186 13 frame->linesize[0]);
187 // update data length in header after RLE
188
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (s->type == RT_BYTE_ENCODED)
189 13 AV_WB32(&avpkt->data[16], s->length);
190
191 13 *got_packet_ptr = 1;
192 13 avpkt->size = bytestream2_tell_p(&s->p);
193 13 return 0;
194 }
195
196 #define OFFSET(x) offsetof(SUNRASTContext, x)
197 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
198 static const AVOption options[] = {
199 { "rle", "Use run-length compression", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
200
201 { NULL },
202 };
203
204 static const AVClass sunrast_class = {
205 .class_name = "sunrast",
206 .item_name = av_default_item_name,
207 .option = options,
208 .version = LIBAVUTIL_VERSION_INT,
209 };
210
211 const FFCodec ff_sunrast_encoder = {
212 .p.name = "sunrast",
213 CODEC_LONG_NAME("Sun Rasterfile image"),
214 .p.type = AVMEDIA_TYPE_VIDEO,
215 .p.id = AV_CODEC_ID_SUNRAST,
216 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
217 .priv_data_size = sizeof(SUNRASTContext),
218 .init = sunrast_encode_init,
219 FF_CODEC_ENCODE_CB(sunrast_encode_frame),
220 .p.priv_class = &sunrast_class,
221 .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24,
222 AV_PIX_FMT_PAL8,
223 AV_PIX_FMT_GRAY8,
224 AV_PIX_FMT_MONOWHITE,
225 AV_PIX_FMT_NONE },
226 };
227