FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/hdrdec.c
Date: 2022-10-02 18:56:10
Exec Total Coverage
Lines: 0 111 0.0%
Branches: 0 84 0.0%

Line Branch Exec Source
1 /*
2 * Radiance HDR image format
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "avcodec.h"
22 #include "bytestream.h"
23 #include "codec_internal.h"
24 #include "decode.h"
25 #include "thread.h"
26
27 #define MINELEN 8
28 #define MAXELEN 0x7fff
29
30 static int hdr_get_line(GetByteContext *gb, uint8_t *buffer, int size)
31 {
32 int n = 0, c;
33
34 memset(buffer, 0, size);
35
36 do {
37 c = bytestream2_get_byte(gb);
38 if (n < size - 1)
39 buffer[n++] = c;
40 } while (bytestream2_get_bytes_left(gb) > 0 && c != '\n');
41
42 return 0;
43 }
44
45 static float convert(int expo, int val)
46 {
47 if (expo == -128) {
48 return 0.f;
49 } else {
50 const float v = val / 256.f;
51
52 return ldexpf(v, expo);
53 }
54 }
55
56 static int decompress(uint8_t *scanline, int w, GetByteContext *gb, const uint8_t *start)
57 {
58 int rshift = 0;
59
60 while (w > 0) {
61 scanline[0] = bytestream2_get_byte(gb);
62 scanline[1] = bytestream2_get_byte(gb);
63 scanline[2] = bytestream2_get_byte(gb);
64 scanline[3] = bytestream2_get_byte(gb);
65
66 if (scanline[0] == 1 &&
67 scanline[1] == 1 &&
68 scanline[2] == 1) {
69 int run = scanline[3];
70 for (int i = run << rshift; i > 0 && w > 0 && scanline >= start + 4; i--) {
71 memcpy(scanline, scanline - 4, 4);
72 scanline += 4;
73 w -= 4;
74 }
75 rshift += 8;
76 if (rshift > 16)
77 break;
78 } else {
79 scanline += 4;
80 w--;
81 rshift = 0;
82 }
83 }
84
85 return 1;
86 }
87
88 static int hdr_decode_frame(AVCodecContext *avctx, AVFrame *p,
89 int *got_frame, AVPacket *avpkt)
90 {
91 int width = 0, height = 0;
92 GetByteContext gb;
93 uint8_t line[512];
94 float sar;
95 int ret;
96
97 bytestream2_init(&gb, avpkt->data, avpkt->size);
98 hdr_get_line(&gb, line, sizeof(line));
99 if (memcmp("#?RADIANCE\n", line, 11))
100 return AVERROR_INVALIDDATA;
101
102 do {
103 hdr_get_line(&gb, line, sizeof(line));
104 if (sscanf(line, "PIXASPECT=%f\n", &sar) == 1)
105 avctx->sample_aspect_ratio = p->sample_aspect_ratio = av_inv_q(av_d2q(sar, 4096));
106 } while (line[0] != '\n' && line[0]);
107
108 hdr_get_line(&gb, line, sizeof(line));
109 if (sscanf(line, "-Y %d +X %d\n", &height, &width) == 2) {
110 ;
111 } else if (sscanf(line, "+Y %d +X %d\n", &height, &width) == 2) {
112 ;
113 } else if (sscanf(line, "-Y %d -X %d\n", &height, &width) == 2) {
114 ;
115 } else if (sscanf(line, "+Y %d -X %d\n", &height, &width) == 2) {
116 ;
117 } else if (sscanf(line, "-X %d +Y %d\n", &width, &height) == 2) {
118 ;
119 } else if (sscanf(line, "+X %d +Y %d\n", &width, &height) == 2) {
120 ;
121 } else if (sscanf(line, "-X %d -Y %d\n", &width, &height) == 2) {
122 ;
123 } else if (sscanf(line, "+X %d -Y %d\n", &width, &height) == 2) {
124 ;
125 }
126
127 if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
128 return ret;
129
130 avctx->pix_fmt = AV_PIX_FMT_GBRPF32;
131
132 if (avctx->skip_frame >= AVDISCARD_ALL)
133 return avpkt->size;
134
135 if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
136 return ret;
137
138 for (int y = 0; y < height; y++) {
139 float *dst_r = (float *)(p->data[2] + y * p->linesize[2]);
140 float *dst_g = (float *)(p->data[0] + y * p->linesize[0]);
141 float *dst_b = (float *)(p->data[1] + y * p->linesize[1]);
142 uint8_t *scanline = p->data[0] + y * p->linesize[0];
143 int i;
144
145 if (width < MINELEN || width > MAXELEN) {
146 decompress(scanline, width, &gb, scanline);
147 goto convert;
148 }
149
150 i = bytestream2_peek_byte(&gb);
151 if (i != 2) {
152 decompress(scanline, width, &gb, scanline);
153 goto convert;
154 }
155 bytestream2_skip(&gb, 1);
156
157 scanline[1] = bytestream2_get_byte(&gb);
158 scanline[2] = bytestream2_get_byte(&gb);
159 i = bytestream2_get_byte(&gb);
160
161 if (scanline[1] != 2 || scanline[2] & 128) {
162 scanline[0] = 2;
163 scanline[3] = i;
164 decompress(scanline + 4, width - 1, &gb, scanline);
165 goto convert;
166 }
167
168 for (int i = 0; i < 4; i++) {
169 uint8_t *scanline = p->data[0] + y * p->linesize[0] + i;
170
171 for (int j = 0; j < width * 4 && bytestream2_get_bytes_left(&gb) > 0;) {
172 int run = bytestream2_get_byte(&gb);
173 if (run > 128) {
174 uint8_t val = bytestream2_get_byte(&gb);
175 run &= 127;
176 while (run--) {
177 if (j >= width * 4)
178 break;
179 scanline[j] = val;
180 j += 4;
181 }
182 } else if (run > 0) {
183 while (run--) {
184 if (j >= width * 4)
185 break;
186 scanline[j] = bytestream2_get_byte(&gb);
187 j += 4;
188 }
189 }
190 }
191 }
192
193 convert:
194 for (int x = 0; x < width; x++) {
195 uint8_t rgbe[4];
196 int expo;
197
198 memcpy(rgbe, p->data[0] + y * p->linesize[0] + x * 4, 4);
199 expo = rgbe[3] - 128;
200
201 dst_r[x] = convert(expo, rgbe[0]);
202 dst_b[x] = convert(expo, rgbe[2]);
203 dst_g[x] = convert(expo, rgbe[1]);
204 }
205 }
206
207 p->key_frame = 1;
208 p->pict_type = AV_PICTURE_TYPE_I;
209
210 *got_frame = 1;
211
212 return avpkt->size;
213 }
214
215 const FFCodec ff_hdr_decoder = {
216 .p.name = "hdr",
217 CODEC_LONG_NAME("HDR (Radiance RGBE format) image"),
218 .p.type = AVMEDIA_TYPE_VIDEO,
219 .p.id = AV_CODEC_ID_RADIANCE_HDR,
220 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
221 .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
222 FF_CODEC_DECODE_CB(hdr_decode_frame),
223 };
224