FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/pnmenc.c
Date: 2024-04-26 14:42:52
Exec Total Coverage
Lines: 85 146 58.2%
Functions: 1 2 50.0%
Branches: 55 88 62.5%

Line Branch Exec Source
1 /*
2 * PNM image format
3 * Copyright (c) 2002, 2003 Fabrice Bellard
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 "config_components.h"
23
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/imgutils.h"
26 #include "libavutil/pixdesc.h"
27 #include "libavutil/float2half.h"
28 #include "avcodec.h"
29 #include "codec_internal.h"
30 #include "encode.h"
31
32 typedef struct PHMEncContext {
33 Float2HalfTables f2h_tables;
34 } PHMEncContext;
35
36 153 static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
37 const AVFrame *p, int *got_packet)
38 {
39 153 PHMEncContext *s = avctx->priv_data;
40 uint8_t *bytestream, *bytestream_start, *bytestream_end;
41 int i, h, h1, c, n, linesize, ret;
42 153 int size = av_image_get_buffer_size(avctx->pix_fmt,
43 avctx->width, avctx->height, 1);
44
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 153 times.
153 if (size < 0)
46 return size;
47
48
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 153 times.
153 if ((ret = ff_get_encode_buffer(avctx, pkt, size + 200U, 0)) < 0)
49 return ret;
50
51 153 bytestream_start =
52 153 bytestream = pkt->data;
53 153 bytestream_end = pkt->data + pkt->size;
54
55 153 h = avctx->height;
56 153 h1 = h;
57
5/10
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 38 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 26 times.
✓ Branch 8 taken 26 times.
✗ Branch 9 not taken.
153 switch (avctx->pix_fmt) {
58 25 case AV_PIX_FMT_MONOWHITE:
59 25 c = '4';
60 25 n = (avctx->width + 7) >> 3;
61 25 break;
62 38 case AV_PIX_FMT_GRAY8:
63 38 c = '5';
64 38 n = avctx->width;
65 38 break;
66 case AV_PIX_FMT_GRAY16BE:
67 c = '5';
68 n = avctx->width * 2;
69 break;
70 38 case AV_PIX_FMT_RGB24:
71 38 c = '6';
72 38 n = avctx->width * 3;
73 38 break;
74 case AV_PIX_FMT_RGB48BE:
75 c = '6';
76 n = avctx->width * 6;
77 break;
78 case AV_PIX_FMT_YUV420P:
79 if (avctx->width & 1 || avctx->height & 1) {
80 av_log(avctx, AV_LOG_ERROR, "pgmyuv needs even width and height\n");
81 return AVERROR(EINVAL);
82 }
83 c = '5';
84 n = avctx->width;
85 h1 = (h * 3) / 2;
86 break;
87 case AV_PIX_FMT_YUV420P16BE:
88 c = '5';
89 n = avctx->width * 2;
90 h1 = (h * 3) / 2;
91 break;
92 26 case AV_PIX_FMT_GBRPF32BE:
93 case AV_PIX_FMT_GBRPF32LE:
94
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (avctx->codec_id == AV_CODEC_ID_PFM) {
95 26 c = 'F';
96 26 n = avctx->width * 4;
97 } else {
98 c = 'H';
99 n = avctx->width * 2;
100 }
101 26 break;
102 26 case AV_PIX_FMT_GRAYF32BE:
103 case AV_PIX_FMT_GRAYF32LE:
104
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (avctx->codec_id == AV_CODEC_ID_PFM) {
105 26 c = 'f';
106 26 n = avctx->width * 4;
107 } else {
108 c = 'h';
109 n = avctx->width * 2;
110 }
111 26 break;
112 default:
113 return -1;
114 }
115 153 snprintf(bytestream, bytestream_end - bytestream,
116 "P%c\n%d %d\n", c, avctx->width, h1);
117 153 bytestream += strlen(bytestream);
118
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 13 times.
153 if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32LE ||
119
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 13 times.
140 avctx->pix_fmt == AV_PIX_FMT_GRAYF32LE ||
120
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 13 times.
127 avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE ||
121
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 101 times.
114 avctx->pix_fmt == AV_PIX_FMT_GRAYF32BE)
122 52 snprintf(bytestream, bytestream_end - bytestream,
123
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13 times.
52 "%f\n", (avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE ||
124
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 26 times.
39 avctx->pix_fmt == AV_PIX_FMT_GRAYF32BE) ? 1.f: -1.f);
125 153 bytestream += strlen(bytestream);
126
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 25 times.
153 if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE &&
127
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 13 times.
128 avctx->pix_fmt != AV_PIX_FMT_GBRPF32LE &&
128
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 13 times.
115 avctx->pix_fmt != AV_PIX_FMT_GRAYF32LE &&
129
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 13 times.
102 avctx->pix_fmt != AV_PIX_FMT_GBRPF32BE &&
130
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 13 times.
89 avctx->pix_fmt != AV_PIX_FMT_GRAYF32BE) {
131 76 int maxdepth = (1 << av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth) - 1;
132 76 snprintf(bytestream, bytestream_end - bytestream,
133 "%d\n", maxdepth);
134 76 bytestream += strlen(bytestream);
135 }
136
137
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 13 times.
153 if ((avctx->pix_fmt == AV_PIX_FMT_GBRPF32LE ||
138
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 127 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
179 avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE) && c == 'F') {
139 /* PFM is encoded from bottom to top */
140 26 const float *r = (const float *)(p->data[2] + p->linesize[2] * (avctx->height - 1));
141 26 const float *g = (const float *)(p->data[0] + p->linesize[0] * (avctx->height - 1));
142 26 const float *b = (const float *)(p->data[1] + p->linesize[1] * (avctx->height - 1));
143
144
2/2
✓ Branch 0 taken 7488 times.
✓ Branch 1 taken 26 times.
7514 for (int i = 0; i < avctx->height; i++) {
145
2/2
✓ Branch 0 taken 2635776 times.
✓ Branch 1 taken 7488 times.
2643264 for (int j = 0; j < avctx->width; j++) {
146 2635776 AV_WN32(bytestream + 0, av_float2int(r[j]));
147 2635776 AV_WN32(bytestream + 4, av_float2int(g[j]));
148 2635776 AV_WN32(bytestream + 8, av_float2int(b[j]));
149 2635776 bytestream += 12;
150 }
151
152 7488 r -= p->linesize[2] / 4;
153 7488 g -= p->linesize[0] / 4;
154 7488 b -= p->linesize[1] / 4;
155 }
156
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 13 times.
127 } else if ((avctx->pix_fmt == AV_PIX_FMT_GRAYF32LE ||
157
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
153 avctx->pix_fmt == AV_PIX_FMT_GRAYF32BE) && c == 'f') {
158 /* PFM is encoded from bottom to top */
159 26 const float *g = (const float *)(p->data[0] + p->linesize[0] * (avctx->height - 1));
160
161
2/2
✓ Branch 0 taken 7488 times.
✓ Branch 1 taken 26 times.
7514 for (int i = 0; i < avctx->height; i++) {
162
2/2
✓ Branch 0 taken 2635776 times.
✓ Branch 1 taken 7488 times.
2643264 for (int j = 0; j < avctx->width; j++) {
163 2635776 AV_WN32(bytestream, av_float2int(g[j]));
164 2635776 bytestream += 4;
165 }
166
167 7488 g -= p->linesize[0] / 4;
168 }
169
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
101 } else if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32 && c == 'H') {
170 const float *r = (const float *)p->data[2];
171 const float *g = (const float *)p->data[0];
172 const float *b = (const float *)p->data[1];
173
174 for (int i = 0; i < avctx->height; i++) {
175 for (int j = 0; j < avctx->width; j++) {
176 AV_WN16(bytestream + 0, float2half(av_float2int(r[j]), &s->f2h_tables));
177 AV_WN16(bytestream + 2, float2half(av_float2int(g[j]), &s->f2h_tables));
178 AV_WN16(bytestream + 4, float2half(av_float2int(b[j]), &s->f2h_tables));
179 bytestream += 6;
180 }
181
182 r += p->linesize[2] / 4;
183 g += p->linesize[0] / 4;
184 b += p->linesize[1] / 4;
185 }
186
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
101 } else if (avctx->pix_fmt == AV_PIX_FMT_GRAYF32 && c == 'h') {
187 const float *g = (const float *)p->data[0];
188
189 for (int i = 0; i < avctx->height; i++) {
190 for (int j = 0; j < avctx->width; j++) {
191 AV_WN16(bytestream, float2half(av_float2int(g[j]), &s->f2h_tables));
192 bytestream += 2;
193 }
194
195 g += p->linesize[0] / 4;
196 }
197 } else {
198 101 const uint8_t *ptr = p->data[0];
199 101 linesize = p->linesize[0];
200
2/2
✓ Branch 0 taken 29088 times.
✓ Branch 1 taken 101 times.
29189 for (i = 0; i < h; i++) {
201 29088 memcpy(bytestream, ptr, n);
202 29088 bytestream += n;
203 29088 ptr += linesize;
204 }
205 }
206
207
2/4
✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 153 times.
153 if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || avctx->pix_fmt == AV_PIX_FMT_YUV420P16BE) {
208 const uint8_t *ptr1 = p->data[1], *ptr2 = p->data[2];
209 h >>= 1;
210 n >>= 1;
211 for (i = 0; i < h; i++) {
212 memcpy(bytestream, ptr1, n);
213 bytestream += n;
214 memcpy(bytestream, ptr2, n);
215 bytestream += n;
216 ptr1 += p->linesize[1];
217 ptr2 += p->linesize[2];
218 }
219 }
220 153 av_shrink_packet(pkt, bytestream - bytestream_start);
221 153 *got_packet = 1;
222
223 153 return 0;
224 }
225
226 #if CONFIG_PGM_ENCODER
227 const FFCodec ff_pgm_encoder = {
228 .p.name = "pgm",
229 CODEC_LONG_NAME("PGM (Portable GrayMap) image"),
230 .p.type = AVMEDIA_TYPE_VIDEO,
231 .p.id = AV_CODEC_ID_PGM,
232 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
233 FF_CODEC_ENCODE_CB(pnm_encode_frame),
234 .p.pix_fmts = (const enum AVPixelFormat[]){
235 AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE
236 },
237 };
238 #endif
239
240 #if CONFIG_PGMYUV_ENCODER
241 const FFCodec ff_pgmyuv_encoder = {
242 .p.name = "pgmyuv",
243 CODEC_LONG_NAME("PGMYUV (Portable GrayMap YUV) image"),
244 .p.type = AVMEDIA_TYPE_VIDEO,
245 .p.id = AV_CODEC_ID_PGMYUV,
246 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
247 FF_CODEC_ENCODE_CB(pnm_encode_frame),
248 .p.pix_fmts = (const enum AVPixelFormat[]){
249 AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE
250 },
251 };
252 #endif
253
254 #if CONFIG_PPM_ENCODER
255 const FFCodec ff_ppm_encoder = {
256 .p.name = "ppm",
257 CODEC_LONG_NAME("PPM (Portable PixelMap) image"),
258 .p.type = AVMEDIA_TYPE_VIDEO,
259 .p.id = AV_CODEC_ID_PPM,
260 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
261 FF_CODEC_ENCODE_CB(pnm_encode_frame),
262 .p.pix_fmts = (const enum AVPixelFormat[]){
263 AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE
264 },
265 };
266 #endif
267
268 #if CONFIG_PBM_ENCODER
269 const FFCodec ff_pbm_encoder = {
270 .p.name = "pbm",
271 CODEC_LONG_NAME("PBM (Portable BitMap) image"),
272 .p.type = AVMEDIA_TYPE_VIDEO,
273 .p.id = AV_CODEC_ID_PBM,
274 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
275 FF_CODEC_ENCODE_CB(pnm_encode_frame),
276 .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE,
277 AV_PIX_FMT_NONE },
278 };
279 #endif
280
281 #if CONFIG_PFM_ENCODER
282 const FFCodec ff_pfm_encoder = {
283 .p.name = "pfm",
284 CODEC_LONG_NAME("PFM (Portable FloatMap) image"),
285 .p.type = AVMEDIA_TYPE_VIDEO,
286 .p.id = AV_CODEC_ID_PFM,
287 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
288 FF_CODEC_ENCODE_CB(pnm_encode_frame),
289 .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32LE,
290 AV_PIX_FMT_GRAYF32LE,
291 AV_PIX_FMT_GBRPF32BE,
292 AV_PIX_FMT_GRAYF32BE,
293 AV_PIX_FMT_NONE },
294 };
295 #endif
296
297 #if CONFIG_PHM_ENCODER
298 static av_cold int phm_enc_init(AVCodecContext *avctx)
299 {
300 PHMEncContext *s = avctx->priv_data;
301
302 ff_init_float2half_tables(&s->f2h_tables);
303
304 return 0;
305 }
306
307 const FFCodec ff_phm_encoder = {
308 .p.name = "phm",
309 CODEC_LONG_NAME("PHM (Portable HalfFloatMap) image"),
310 .p.type = AVMEDIA_TYPE_VIDEO,
311 .p.id = AV_CODEC_ID_PHM,
312 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
313 .priv_data_size = sizeof(PHMEncContext),
314 .init = phm_enc_init,
315 FF_CODEC_ENCODE_CB(pnm_encode_frame),
316 .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32,
317 AV_PIX_FMT_GRAYF32,
318 AV_PIX_FMT_NONE },
319 };
320 #endif
321