FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dpx.c
Date: 2026-01-23 14:02:51
Exec Total Coverage
Lines: 263 513 51.3%
Functions: 8 11 72.7%
Branches: 112 262 42.7%

Line Branch Exec Source
1 /*
2 * DPX (.dpx) image decoder
3 * Copyright (c) 2009 Jimmy Christensen
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/avstring.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/intfloat.h"
25 #include "libavutil/imgutils.h"
26 #include "libavutil/timecode.h"
27 #include "avcodec.h"
28 #include "codec_internal.h"
29 #include "decode.h"
30 #include "dpx.h"
31
32 #include "thread.h"
33 #include "hwconfig.h"
34 #include "hwaccel_internal.h"
35 #include "config_components.h"
36
37 4257978 static unsigned int read16(const uint8_t **ptr, int is_big)
38 {
39 unsigned int temp;
40
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4257974 times.
4257978 if (is_big) {
41 4 temp = AV_RB16(*ptr);
42 } else {
43 4257974 temp = AV_RL16(*ptr);
44 }
45 4257978 *ptr += 2;
46 4257978 return temp;
47 }
48
49 3044637 static unsigned int read32(const uint8_t **ptr, int is_big)
50 {
51 unsigned int temp;
52
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3044615 times.
3044637 if (is_big) {
53 22 temp = AV_RB32(*ptr);
54 } else {
55 3044615 temp = AV_RL32(*ptr);
56 }
57 3044637 *ptr += 4;
58 3044637 return temp;
59 }
60
61 static uint16_t read10in32_gray(const uint8_t **ptr, uint32_t *lbuf,
62 int *n_datum, int is_big, int shift)
63 {
64 uint16_t temp;
65
66 if (*n_datum)
67 (*n_datum)--;
68 else {
69 *lbuf = read32(ptr, is_big);
70 *n_datum = 2;
71 }
72
73 temp = *lbuf >> shift & 0x3FF;
74 *lbuf = *lbuf >> 10;
75
76 return temp;
77 }
78
79 9131904 static uint16_t read10in32(const uint8_t **ptr, uint32_t *lbuf,
80 int *n_datum, int is_big, int shift)
81 {
82
2/2
✓ Branch 0 taken 6087936 times.
✓ Branch 1 taken 3043968 times.
9131904 if (*n_datum)
83 6087936 (*n_datum)--;
84 else {
85 3043968 *lbuf = read32(ptr, is_big);
86 3043968 *n_datum = 2;
87 }
88
89 9131904 *lbuf = *lbuf << 10 | *lbuf >> shift & 0x3FFFFF;
90
91 9131904 return *lbuf & 0x3FF;
92 }
93
94 static uint16_t read12in32(const uint8_t **ptr, uint32_t *lbuf,
95 int *n_datum, int is_big)
96 {
97 if (*n_datum)
98 (*n_datum)--;
99 else {
100 *lbuf = read32(ptr, is_big);
101 *n_datum = 7;
102 }
103
104 switch (*n_datum){
105 case 7: return *lbuf & 0xFFF;
106 case 6: return (*lbuf >> 12) & 0xFFF;
107 case 5: {
108 uint32_t c = *lbuf >> 24;
109 *lbuf = read32(ptr, is_big);
110 c |= *lbuf << 8;
111 return c & 0xFFF;
112 }
113 case 4: return (*lbuf >> 4) & 0xFFF;
114 case 3: return (*lbuf >> 16) & 0xFFF;
115 case 2: {
116 uint32_t c = *lbuf >> 28;
117 *lbuf = read32(ptr, is_big);
118 c |= *lbuf << 4;
119 return c & 0xFFF;
120 }
121 case 1: return (*lbuf >> 8) & 0xFFF;
122 default: return *lbuf >> 20;
123 }
124 }
125
126 93 static void unpack_frame(AVCodecContext *avctx, AVFrame *p, const uint8_t *buf,
127 int elements, int endian)
128 {
129 int i, x, y;
130 93 DPXDecContext *dpx = avctx->priv_data;
131
132 uint8_t *ptr[AV_NUM_DATA_POINTERS];
133 93 unsigned int rgbBuffer = 0;
134 93 int n_datum = 0;
135
136
2/2
✓ Branch 0 taken 744 times.
✓ Branch 1 taken 93 times.
837 for (i=0; i<AV_NUM_DATA_POINTERS; i++)
137 744 ptr[i] = p->data[i];
138
139
4/6
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
93 switch (avctx->bits_per_raw_sample) {
140 30 case 10:
141
2/2
✓ Branch 0 taken 8544 times.
✓ Branch 1 taken 30 times.
8574 for (x = 0; x < avctx->height; x++) {
142 8544 uint16_t *dst[4] = {(uint16_t*)ptr[0],
143 8544 (uint16_t*)ptr[1],
144 8544 (uint16_t*)ptr[2],
145 8544 (uint16_t*)ptr[3]};
146
2/6
✓ Branch 0 taken 8544 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8544 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8544 int shift = elements > 1 ? dpx->packing == 1 ? 22 : 20 : dpx->packing == 1 ? 2 : 0;
147
2/2
✓ Branch 0 taken 3043968 times.
✓ Branch 1 taken 8544 times.
3052512 for (y = 0; y < avctx->width; y++) {
148
1/2
✓ Branch 0 taken 3043968 times.
✗ Branch 1 not taken.
3043968 if (elements >= 3)
149 3043968 *dst[2]++ = read10in32(&buf, &rgbBuffer,
150 &n_datum, endian, shift);
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3043968 times.
3043968 if (elements == 1)
152 *dst[0]++ = read10in32_gray(&buf, &rgbBuffer,
153 &n_datum, endian, shift);
154 else
155 3043968 *dst[0]++ = read10in32(&buf, &rgbBuffer,
156 &n_datum, endian, shift);
157
1/2
✓ Branch 0 taken 3043968 times.
✗ Branch 1 not taken.
3043968 if (elements >= 2)
158 3043968 *dst[1]++ = read10in32(&buf, &rgbBuffer,
159 &n_datum, endian, shift);
160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3043968 times.
3043968 if (elements == 4)
161 *dst[3]++ =
162 read10in32(&buf, &rgbBuffer,
163 &n_datum, endian, shift);
164 }
165
1/2
✓ Branch 0 taken 8544 times.
✗ Branch 1 not taken.
8544 if (!dpx->unpadded_10bit)
166 8544 n_datum = 0;
167
2/2
✓ Branch 0 taken 25632 times.
✓ Branch 1 taken 8544 times.
34176 for (i = 0; i < elements; i++)
168 25632 ptr[i] += p->linesize[i];
169 }
170 30 break;
171 14 case 12:
172
2/2
✓ Branch 0 taken 4032 times.
✓ Branch 1 taken 14 times.
4046 for (x = 0; x < avctx->height; x++) {
173 4032 uint16_t *dst[4] = {(uint16_t*)ptr[0],
174 4032 (uint16_t*)ptr[1],
175 4032 (uint16_t*)ptr[2],
176 4032 (uint16_t*)ptr[3]};
177
1/2
✓ Branch 0 taken 4032 times.
✗ Branch 1 not taken.
4032 int shift = dpx->packing == 1 ? 4 : 0;
178
2/2
✓ Branch 0 taken 1419264 times.
✓ Branch 1 taken 4032 times.
1423296 for (y = 0; y < avctx->width; y++) {
179
1/2
✓ Branch 0 taken 1419264 times.
✗ Branch 1 not taken.
1419264 if (dpx->packing) {
180
1/2
✓ Branch 0 taken 1419264 times.
✗ Branch 1 not taken.
1419264 if (elements >= 3)
181 1419264 *dst[2]++ = read16(&buf, endian) >> shift & 0xFFF;
182 1419264 *dst[0]++ = read16(&buf, endian) >> shift & 0xFFF;
183
1/2
✓ Branch 0 taken 1419264 times.
✗ Branch 1 not taken.
1419264 if (elements >= 2)
184 1419264 *dst[1]++ = read16(&buf, endian) >> shift & 0xFFF;
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1419264 times.
1419264 if (elements == 4)
186 *dst[3]++ = read16(&buf, endian) >> shift & 0xFFF;
187 } else {
188 if (elements >= 3)
189 *dst[2]++ = read12in32(&buf, &rgbBuffer,
190 &n_datum, endian);
191 *dst[0]++ = read12in32(&buf, &rgbBuffer,
192 &n_datum, endian);
193 if (elements >= 2)
194 *dst[1]++ = read12in32(&buf, &rgbBuffer,
195 &n_datum, endian);
196 if (elements == 4)
197 *dst[3]++ = read12in32(&buf, &rgbBuffer,
198 &n_datum, endian);
199 }
200 }
201 4032 n_datum = 0;
202
2/2
✓ Branch 0 taken 12096 times.
✓ Branch 1 taken 4032 times.
16128 for (i = 0; i < elements; i++)
203 12096 ptr[i] += p->linesize[i];
204 // Jump to next aligned position
205 4032 buf += dpx->need_align;
206 }
207 14 break;
208 case 32:
209 if (elements == 1) {
210 av_image_copy_plane(ptr[0], p->linesize[0],
211 buf, dpx->stride,
212 elements * avctx->width * 4, avctx->height);
213 } else {
214 for (y = 0; y < avctx->height; y++) {
215 ptr[0] = p->data[0] + y * p->linesize[0];
216 ptr[1] = p->data[1] + y * p->linesize[1];
217 ptr[2] = p->data[2] + y * p->linesize[2];
218 ptr[3] = p->data[3] + y * p->linesize[3];
219 for (x = 0; x < avctx->width; x++) {
220 AV_WN32(ptr[2], AV_RN32(buf));
221 AV_WN32(ptr[0], AV_RN32(buf + 4));
222 AV_WN32(ptr[1], AV_RN32(buf + 8));
223 if (avctx->pix_fmt == AV_PIX_FMT_GBRAPF32BE ||
224 avctx->pix_fmt == AV_PIX_FMT_GBRAPF32LE) {
225 AV_WN32(ptr[3], AV_RN32(buf + 12));
226 buf += 4;
227 ptr[3] += 4;
228 }
229
230 buf += 12;
231 ptr[2] += 4;
232 ptr[0] += 4;
233 ptr[1] += 4;
234 }
235 }
236 }
237 break;
238 30 case 16:
239 30 elements *= 2;
240 // fall-through
241 49 case 8:
242
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if ( avctx->pix_fmt == AV_PIX_FMT_YUVA444P
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 || avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
244 for (x = 0; x < avctx->height; x++) {
245 ptr[0] = p->data[0] + x * p->linesize[0];
246 ptr[1] = p->data[1] + x * p->linesize[1];
247 ptr[2] = p->data[2] + x * p->linesize[2];
248 ptr[3] = p->data[3] + x * p->linesize[3];
249 for (y = 0; y < avctx->width; y++) {
250 *ptr[1]++ = *buf++;
251 *ptr[0]++ = *buf++;
252 *ptr[2]++ = *buf++;
253 if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P)
254 *ptr[3]++ = *buf++;
255 }
256 }
257 } else {
258 49 av_image_copy_plane(ptr[0], p->linesize[0],
259 buf, dpx->stride,
260 49 elements * avctx->width, avctx->height);
261 }
262 49 break;
263 }
264 93 }
265
266 18 static enum AVPixelFormat get_pixel_format(AVCodecContext *avctx,
267 enum AVPixelFormat pix_fmt)
268 {
269 18 enum AVPixelFormat pix_fmts[] = {
270 #if CONFIG_DPX_VULKAN_HWACCEL
271 AV_PIX_FMT_VULKAN,
272 #endif
273 pix_fmt,
274 AV_PIX_FMT_NONE,
275 };
276
277 18 return ff_get_format(avctx, pix_fmts);
278 }
279
280 93 static int decode_frame(AVCodecContext *avctx, AVFrame *p,
281 int *got_frame, AVPacket *avpkt)
282 {
283 93 DPXDecContext *dpx = avctx->priv_data;
284
285 enum AVPixelFormat pix_fmt;
286 93 const uint8_t *buf = avpkt->data;
287 93 int buf_size = avpkt->size;
288 93 uint32_t header_version, version = 0;
289 93 char creator[101] = { 0 };
290 93 char input_device[33] = { 0 };
291
292 unsigned int offset;
293 int magic_num;
294 int i, j, ret;
295 int w, h, descriptor;
296 int yuv, color_trc, color_spec;
297 int encoding;
298
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (avpkt->size <= 1634) {
300 av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
301 return AVERROR_INVALIDDATA;
302 }
303
304 93 magic_num = AV_RB32(buf);
305 93 buf += 4;
306
307 /* Check if the files "magic number" is "SDPX" which means it uses
308 * big-endian or XPDS which is for little-endian files */
309
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 2 times.
93 if (magic_num == AV_RL32("SDPX")) {
310 91 dpx->endian = 0;
311
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 } else if (magic_num == AV_RB32("SDPX")) {
312 2 dpx->endian = 1;
313 } else {
314 av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
315 return AVERROR_INVALIDDATA;
316 }
317
318 93 offset = read32(&buf, dpx->endian);
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (avpkt->size <= offset) {
320 av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
321 return AVERROR_INVALIDDATA;
322 }
323
324 93 header_version = read32(&buf, 0);
325
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 4 times.
93 if (header_version == MKTAG('V','1','.','0'))
326 89 version = 1;
327
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 89 times.
93 if (header_version == MKTAG('V','2','.','0'))
328 4 version = 2;
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (!version)
330 av_log(avctx, AV_LOG_WARNING, "Unknown header format version %s.\n",
331 av_fourcc2str(header_version));
332
333 // Check encryption
334 93 buf = avpkt->data + 660;
335 93 ret = read32(&buf, dpx->endian);
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (ret != 0xFFFFFFFF) {
337 avpriv_report_missing_feature(avctx, "Encryption");
338 av_log(avctx, AV_LOG_WARNING, "The image is encrypted and may "
339 "not properly decode.\n");
340 }
341
342 // Need to end in 0x304 offset from start of file
343 93 buf = avpkt->data + 0x304;
344 93 w = read32(&buf, dpx->endian);
345 93 h = read32(&buf, dpx->endian);
346
347
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
93 if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
348 return ret;
349
350 // Need to end in 0x320 to read the descriptor
351 93 buf += 20;
352 93 descriptor = buf[0];
353 93 color_trc = buf[1];
354 93 color_spec = buf[2];
355
356 // Need to end in 0x323 to read the bits per color
357 93 buf += 3;
358 93 avctx->bits_per_raw_sample = buf[0];
359 93 buf++;
360 93 dpx->packing = read16(&buf, dpx->endian);
361 93 encoding = read16(&buf, dpx->endian);
362
363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (encoding) {
364 avpriv_report_missing_feature(avctx, "Encoding %d", encoding);
365 return AVERROR_PATCHWELCOME;
366 }
367
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (avctx->bits_per_raw_sample > 31)
369 return AVERROR_INVALIDDATA;
370
371 93 buf += 820;
372 93 avctx->sample_aspect_ratio.num = read32(&buf, dpx->endian);
373 93 avctx->sample_aspect_ratio.den = read32(&buf, dpx->endian);
374
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
93 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
375 2 av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
376 2 avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den,
377 0x10000);
378 else
379 91 avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
380
381 /* preferred frame rate from Motion-picture film header */
382
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 89 times.
93 if (offset >= 1724 + 4) {
383 4 buf = avpkt->data + 1724;
384 4 i = read32(&buf, dpx->endian);
385
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 if(i && i != 0xFFFFFFFF) {
386 2 AVRational q = av_d2q(av_int2float(i), 4096);
387
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (q.num > 0 && q.den > 0)
388 2 avctx->framerate = q;
389 }
390 }
391
392 /* alternative frame rate from television header */
393
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 89 times.
93 if (offset >= 1940 + 4 &&
394
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 !(avctx->framerate.num && avctx->framerate.den)) {
395 2 buf = avpkt->data + 1940;
396 2 i = read32(&buf, dpx->endian);
397
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if(i && i != 0xFFFFFFFF) {
398 AVRational q = av_d2q(av_int2float(i), 4096);
399 if (q.num > 0 && q.den > 0)
400 avctx->framerate = q;
401 }
402 }
403
404 /* SMPTE TC from television header */
405
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 89 times.
93 if (offset >= 1920 + 4) {
406 uint32_t tc;
407 uint32_t *tc_sd;
408 char tcbuf[AV_TIMECODE_STR_SIZE];
409
410 4 buf = avpkt->data + 1920;
411 // read32 to native endian, av_bswap32 to opposite of native for
412 // compatibility with av_timecode_make_smpte_tc_string2 etc
413 4 tc = av_bswap32(read32(&buf, dpx->endian));
414
415
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (i != 0xFFFFFFFF) {
416 AVFrameSideData *tcside;
417 4 ret = ff_frame_new_side_data(avctx, p, AV_FRAME_DATA_S12M_TIMECODE,
418 sizeof(uint32_t) * 4, &tcside);
419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
420 return ret;
421
422
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (tcside) {
423 4 tc_sd = (uint32_t*)tcside->data;
424 4 tc_sd[0] = 1;
425 4 tc_sd[1] = tc;
426
427 4 av_timecode_make_smpte_tc_string2(tcbuf, avctx->framerate,
428 4 tc_sd[1], 0, 0);
429 4 av_dict_set(&p->metadata, "timecode", tcbuf, 0);
430 }
431 }
432 }
433
434 /* color range from television header */
435
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 89 times.
93 if (offset >= 1964 + 4) {
436 4 buf = avpkt->data + 1952;
437 4 i = read32(&buf, dpx->endian);
438
439 4 buf = avpkt->data + 1964;
440 4 j = read32(&buf, dpx->endian);
441
442
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (i != 0xFFFFFFFF && j != 0xFFFFFFFF) {
443 float minCV, maxCV;
444 4 minCV = av_int2float(i);
445 4 maxCV = av_int2float(j);
446
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (avctx->bits_per_raw_sample >= 1 &&
447
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 minCV == 0.0f && maxCV == ((1U<<avctx->bits_per_raw_sample) - 1)) {
448 2 avctx->color_range = AVCOL_RANGE_JPEG;
449
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 } else if (avctx->bits_per_raw_sample >= 8 &&
450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 minCV == (1 <<(avctx->bits_per_raw_sample - 4)) &&
451 maxCV == (235<<(avctx->bits_per_raw_sample - 8))) {
452 avctx->color_range = AVCOL_RANGE_MPEG;
453 }
454 }
455 }
456
457
2/7
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
93 switch (descriptor) {
458 case 1: // R
459 case 2: // G
460 case 3: // B
461 case 4: // A
462 case 6: // Y
463 dpx->components = 1;
464 yuv = 1;
465 break;
466 79 case 50: // RGB
467 79 dpx->components = 3;
468 79 yuv = 0;
469 79 break;
470 14 case 52: // ABGR
471 case 51: // RGBA
472 14 dpx->components = 4;
473 14 yuv = 0;
474 14 break;
475 case 100: // UYVY422
476 dpx->components = 2;
477 yuv = 1;
478 break;
479 case 102: // UYV444
480 dpx->components = 3;
481 yuv = 1;
482 break;
483 case 103: // UYVA4444
484 dpx->components = 4;
485 yuv = 1;
486 break;
487 default:
488 avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor);
489 return AVERROR_PATCHWELCOME;
490 }
491
492
4/7
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
93 switch (avctx->bits_per_raw_sample) {
493 19 case 8:
494 19 dpx->stride = avctx->width * dpx->components;
495 19 break;
496 30 case 10:
497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!dpx->packing) {
498 av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
499 return -1;
500 }
501 30 dpx->stride = (avctx->width * dpx->components + 2) / 3 * 4;
502 30 break;
503 14 case 12:
504 14 dpx->stride = avctx->width * dpx->components;
505
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (dpx->packing) {
506 14 dpx->stride *= 2;
507 } else {
508 dpx->stride *= 3;
509 if (dpx->stride % 8) {
510 dpx->stride /= 8;
511 dpx->stride++;
512 dpx->stride *= 8;
513 }
514 dpx->stride /= 2;
515 }
516 14 break;
517 30 case 16:
518 30 dpx->stride = 2 * avctx->width * dpx->components;
519 30 break;
520 case 32:
521 dpx->stride = 4 * avctx->width * dpx->components;
522 break;
523 case 1:
524 case 64:
525 avpriv_report_missing_feature(avctx, "Depth %d", avctx->bits_per_raw_sample);
526 return AVERROR_PATCHWELCOME;
527 default:
528 return AVERROR_INVALIDDATA;
529 }
530
531
3/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✓ Branch 5 taken 2 times.
93 switch (color_trc) {
532 5 case DPX_TRC_LINEAR:
533 5 avctx->color_trc = AVCOL_TRC_LINEAR;
534 5 break;
535 case DPX_TRC_SMPTE_274:
536 case DPX_TRC_ITU_R_709_4:
537 avctx->color_trc = AVCOL_TRC_BT709;
538 break;
539 case DPX_TRC_ITU_R_601_625:
540 case DPX_TRC_ITU_R_601_525:
541 case DPX_TRC_SMPTE_170:
542 avctx->color_trc = AVCOL_TRC_SMPTE170M;
543 break;
544 case DPX_TRC_ITU_R_624_4_PAL:
545 avctx->color_trc = AVCOL_TRC_GAMMA28;
546 break;
547 86 case DPX_TRC_USER_DEFINED:
548 case DPX_TRC_UNSPECIFIED_VIDEO:
549 /* Nothing to do */
550 86 break;
551 2 default:
552 2 av_log(avctx, AV_LOG_VERBOSE, "Cannot map DPX transfer characteristic "
553 "%d to color_trc.\n", color_trc);
554 2 break;
555 }
556
557
3/5
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 86 times.
✓ Branch 4 taken 5 times.
93 switch (color_spec) {
558 2 case DPX_COL_SPEC_SMPTE_274:
559 case DPX_COL_SPEC_ITU_R_709_4:
560 2 avctx->color_primaries = AVCOL_PRI_BT709;
561 2 break;
562 case DPX_COL_SPEC_ITU_R_601_625:
563 case DPX_COL_SPEC_ITU_R_624_4_PAL:
564 avctx->color_primaries = AVCOL_PRI_BT470BG;
565 break;
566 case DPX_COL_SPEC_ITU_R_601_525:
567 case DPX_COL_SPEC_SMPTE_170:
568 avctx->color_primaries = AVCOL_PRI_SMPTE170M;
569 break;
570 86 case DPX_COL_SPEC_USER_DEFINED:
571 case DPX_COL_SPEC_UNSPECIFIED_VIDEO:
572 /* Nothing to do */
573 86 break;
574 5 default:
575 5 av_log(avctx, AV_LOG_VERBOSE, "Cannot map DPX color specification "
576 "%d to color_primaries.\n", color_spec);
577 5 break;
578 }
579
580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (yuv) {
581 switch (color_spec) {
582 case DPX_COL_SPEC_SMPTE_274:
583 case DPX_COL_SPEC_ITU_R_709_4:
584 avctx->colorspace = AVCOL_SPC_BT709;
585 break;
586 case DPX_COL_SPEC_ITU_R_601_625:
587 case DPX_COL_SPEC_ITU_R_624_4_PAL:
588 avctx->colorspace = AVCOL_SPC_BT470BG;
589 break;
590 case DPX_COL_SPEC_ITU_R_601_525:
591 case DPX_COL_SPEC_SMPTE_170:
592 avctx->colorspace = AVCOL_SPC_SMPTE170M;
593 break;
594 case DPX_COL_SPEC_USER_DEFINED:
595 case DPX_COL_SPEC_UNSPECIFIED_VIDEO:
596 /* Nothing to do */
597 break;
598 default:
599 av_log(avctx, AV_LOG_INFO, "Cannot map DPX color specification "
600 "%d to colorspace.\n", color_spec);
601 break;
602 }
603 } else {
604 93 avctx->colorspace = AVCOL_SPC_RGB;
605 }
606
607 93 av_strlcpy(creator, avpkt->data + 160, 100);
608 93 creator[100] = '\0';
609 93 av_dict_set(&p->metadata, "Creator", creator, 0);
610
611 93 av_strlcpy(input_device, avpkt->data + 1556, 32);
612 93 input_device[32] = '\0';
613 93 av_dict_set(&p->metadata, "Input Device", input_device, 0);
614
615 // Some devices do not pad 10bit samples to whole 32bit words per row
616 93 dpx->unpadded_10bit = 0;
617
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
93 if (!memcmp(input_device, "Scanity", 7) ||
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 !memcmp(creator, "Lasergraphics Inc.", 18)) {
619 if (avctx->bits_per_raw_sample == 10)
620 dpx->unpadded_10bit = 1;
621 }
622
623 // Table 3c: Runs will always break at scan line boundaries. Packing
624 // will always break to the next 32-bit word at scan-line boundaries.
625 // Unfortunately, the encoder produced invalid files, so attempt
626 // to detect it
627 // Also handle special case with unpadded content
628 93 dpx->need_align = FFALIGN(dpx->stride, 4);
629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (dpx->need_align*avctx->height + (int64_t)offset > avpkt->size &&
630 (!dpx->unpadded_10bit || (avctx->width * avctx->height * dpx->components + 2) / 3 * 4 + (int64_t)offset > avpkt->size)) {
631 // Alignment seems unappliable, try without
632 if (dpx->stride*avctx->height + (int64_t)offset > avpkt->size || dpx->unpadded_10bit) {
633 av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
634 return AVERROR_INVALIDDATA;
635 } else {
636 av_log(avctx, AV_LOG_INFO, "Decoding DPX without scanline "
637 "alignment.\n");
638 dpx->need_align = 0;
639 }
640 } else {
641 93 dpx->need_align -= dpx->stride;
642 93 dpx->stride = FFALIGN(dpx->stride, 4);
643 }
644
645
6/26
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 14 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 14 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 14 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
93 switch (1000 * descriptor + 10 * avctx->bits_per_raw_sample + dpx->endian) {
646 case 1081:
647 case 1080:
648 case 2081:
649 case 2080:
650 case 3081:
651 case 3080:
652 case 4081:
653 case 4080:
654 case 6081:
655 case 6080:
656 pix_fmt = AV_PIX_FMT_GRAY8;
657 break;
658 case 6121:
659 case 6120:
660 pix_fmt = AV_PIX_FMT_GRAY12;
661 break;
662 case 1320:
663 case 2320:
664 case 3320:
665 case 4320:
666 case 6320:
667 pix_fmt = AV_PIX_FMT_GRAYF32LE;
668 break;
669 case 1321:
670 case 2321:
671 case 3321:
672 case 4321:
673 case 6321:
674 pix_fmt = AV_PIX_FMT_GRAYF32BE;
675 break;
676 19 case 50081:
677 case 50080:
678 19 pix_fmt = AV_PIX_FMT_RGB24;
679 19 break;
680 case 52081:
681 case 52080:
682 pix_fmt = AV_PIX_FMT_ABGR;
683 break;
684 case 51081:
685 case 51080:
686 pix_fmt = AV_PIX_FMT_RGBA;
687 break;
688 30 case 50100:
689 case 50101:
690 30 pix_fmt = AV_PIX_FMT_GBRP10;
691 30 break;
692 case 51100:
693 case 51101:
694 pix_fmt = AV_PIX_FMT_GBRAP10;
695 break;
696 14 case 50120:
697 case 50121:
698 14 pix_fmt = AV_PIX_FMT_GBRP12;
699 14 break;
700 case 51120:
701 case 51121:
702 pix_fmt = AV_PIX_FMT_GBRAP12;
703 break;
704 case 6100:
705 case 6101:
706 pix_fmt = AV_PIX_FMT_GRAY10;
707 break;
708 case 6161:
709 pix_fmt = AV_PIX_FMT_GRAY16BE;
710 break;
711 case 6160:
712 pix_fmt = AV_PIX_FMT_GRAY16LE;
713 break;
714 2 case 50161:
715 2 pix_fmt = AV_PIX_FMT_RGB48BE;
716 2 break;
717 14 case 50160:
718 14 pix_fmt = AV_PIX_FMT_RGB48LE;
719 14 break;
720 case 51161:
721 pix_fmt = AV_PIX_FMT_RGBA64BE;
722 break;
723 14 case 51160:
724 14 pix_fmt = AV_PIX_FMT_RGBA64LE;
725 14 break;
726 case 50320:
727 pix_fmt = AV_PIX_FMT_GBRPF32LE;
728 break;
729 case 50321:
730 pix_fmt = AV_PIX_FMT_GBRPF32BE;
731 break;
732 case 51320:
733 pix_fmt = AV_PIX_FMT_GBRAPF32LE;
734 break;
735 case 51321:
736 pix_fmt = AV_PIX_FMT_GBRAPF32BE;
737 break;
738 case 100081:
739 pix_fmt = AV_PIX_FMT_UYVY422;
740 break;
741 case 102081:
742 pix_fmt = AV_PIX_FMT_YUV444P;
743 break;
744 case 103081:
745 pix_fmt = AV_PIX_FMT_YUVA444P;
746 break;
747 default:
748 av_log(avctx, AV_LOG_ERROR, "Unsupported format %d\n",
749 1000 * descriptor + 10 * avctx->bits_per_raw_sample + dpx->endian);
750 return AVERROR_PATCHWELCOME;
751 }
752
753
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 75 times.
93 if (pix_fmt != dpx->pix_fmt) {
754 18 dpx->pix_fmt = pix_fmt;
755
756 18 ret = get_pixel_format(avctx, pix_fmt);
757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
758 return ret;
759
760 18 avctx->pix_fmt = ret;
761 }
762
763 93 ff_set_sar(avctx, avctx->sample_aspect_ratio);
764
765
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
93 if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
766 return ret;
767
768 // Move pointer to offset from start of file
769 93 buf = avpkt->data + offset;
770 93 dpx->frame = p;
771
772 /* Start */
773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
93 if (avctx->hwaccel) {
774 const FFHWAccel *hwaccel = ffhwaccel(avctx->hwaccel);
775
776 ret = ff_hwaccel_frame_priv_alloc(avctx, &dpx->hwaccel_picture_private);
777 if (ret < 0)
778 return ret;
779
780 ret = hwaccel->start_frame(avctx, avpkt->buf, buf, avpkt->size - offset);
781 if (ret < 0)
782 return ret;
783
784 ret = hwaccel->decode_slice(avctx, buf, avpkt->size - offset);
785 if (ret < 0)
786 return ret;
787
788 ret = hwaccel->end_frame(avctx);
789 if (ret < 0)
790 return ret;
791
792 av_refstruct_unref(&dpx->hwaccel_picture_private);
793 } else {
794 93 unpack_frame(avctx, p, buf, dpx->components, dpx->endian);
795 }
796
797 93 p->pict_type = AV_PICTURE_TYPE_I;
798 93 p->flags |= AV_FRAME_FLAG_KEY;
799
800 93 *got_frame = 1;
801
802 93 return buf_size;
803 }
804
805 #if HAVE_THREADS
806 static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
807 {
808 DPXDecContext *ssrc = src->priv_data;
809 DPXDecContext *sdst = dst->priv_data;
810
811 sdst->pix_fmt = ssrc->pix_fmt;
812
813 return 0;
814 }
815 #endif
816
817 18 static av_cold int decode_end(AVCodecContext *avctx)
818 {
819 18 DPXDecContext *dpx = avctx->priv_data;
820 18 av_refstruct_unref(&dpx->hwaccel_picture_private);
821 18 return 0;
822 }
823
824 18 static av_cold int decode_init(AVCodecContext *avctx)
825 {
826 18 DPXDecContext *dpx = avctx->priv_data;
827 18 dpx->pix_fmt = AV_PIX_FMT_NONE;
828 18 return 0;
829 }
830
831 const FFCodec ff_dpx_decoder = {
832 .p.name = "dpx",
833 CODEC_LONG_NAME("DPX (Digital Picture Exchange) image"),
834 .priv_data_size = sizeof(DPXDecContext),
835 .p.type = AVMEDIA_TYPE_VIDEO,
836 .p.id = AV_CODEC_ID_DPX,
837 FF_CODEC_DECODE_CB(decode_frame),
838 .init = decode_init,
839 .close = decode_end,
840 UPDATE_THREAD_CONTEXT(update_thread_context),
841 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
842 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP |
843 FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
844 .hw_configs = (const AVCodecHWConfigInternal *const []) {
845 #if CONFIG_DPX_VULKAN_HWACCEL
846 HWACCEL_VULKAN(dpx),
847 #endif
848 NULL
849 },
850 };
851