FFmpeg
Loading...
Searching...
No Matches
hdrdec.c
Go to the documentation of this file.
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
30static 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
45static 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
56static int decompress(uint8_t *scanline, int w, GetByteContext *gb, const uint8_t *start)
57{
58 int rshift = 0;
59
60 while (w > 0) {
63 scanline[0] = bytestream2_get_byte(gb);
64 scanline[1] = bytestream2_get_byte(gb);
65 scanline[2] = bytestream2_get_byte(gb);
66 scanline[3] = bytestream2_get_byte(gb);
67
68 if (scanline[0] == 1 &&
69 scanline[1] == 1 &&
70 scanline[2] == 1) {
71 int run = scanline[3];
72 for (int i = run << rshift; i > 0 && w > 0 && scanline >= start + 4; i--) {
73 memcpy(scanline, scanline - 4, 4);
74 scanline += 4;
75 w--;
76 }
77 rshift += 8;
78 if (rshift > 16)
79 break;
80 } else {
81 scanline += 4;
82 w--;
83 rshift = 0;
84 }
85 }
86
87 return 1;
88}
89
91 int *got_frame, AVPacket *avpkt)
92{
93 int width = 0, height = 0;
95 uint8_t line[512];
96 float sar;
97 int ret;
98
99 bytestream2_init(&gb, avpkt->data, avpkt->size);
100 hdr_get_line(&gb, line, sizeof(line));
101 if (memcmp("#?RADIANCE\n", line, 11) && memcmp("#?RGBE\n", line, 7))
102 return AVERROR_INVALIDDATA;
103
104 do {
105 hdr_get_line(&gb, line, sizeof(line));
106 if (sscanf(line, "PIXASPECT=%f\n", &sar) == 1)
107 avctx->sample_aspect_ratio = p->sample_aspect_ratio = av_inv_q(av_d2q(sar, 4096));
108 } while (line[0] != '\n' && line[0]);
109
110 hdr_get_line(&gb, line, sizeof(line));
111 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, "+Y %d -X %d\n", &height, &width) == 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 } else if (sscanf(line, "+X %d -Y %d\n", &width, &height) == 2) {
126 ;
127 }
128
129 if (bytestream2_get_bytes_left(&gb) < height * 4)
130 return AVERROR_INVALIDDATA;
131
132 if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
133 return ret;
134
136
137 if (avctx->skip_frame >= AVDISCARD_ALL)
138 return avpkt->size;
139
140 if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
141 return ret;
142
143 for (int y = 0; y < height; y++) {
144 float *dst_r = (float *)(p->data[2] + y * p->linesize[2]);
145 float *dst_g = (float *)(p->data[0] + y * p->linesize[0]);
146 float *dst_b = (float *)(p->data[1] + y * p->linesize[1]);
147 uint8_t *scanline = p->data[0] + y * p->linesize[0];
148 int i;
149
151 ret = decompress(scanline, width, &gb, scanline);
152 if (ret < 0)
153 return ret;
154 goto convert;
155 }
156
157 i = bytestream2_peek_byte(&gb);
158 if (i != 2) {
159 ret = decompress(scanline, width, &gb, scanline);
160 if (ret < 0)
161 return ret;
162 goto convert;
163 }
164 bytestream2_skip(&gb, 1);
165
166 scanline[1] = bytestream2_get_byte(&gb);
167 scanline[2] = bytestream2_get_byte(&gb);
168 i = bytestream2_get_byte(&gb);
169
170 if (scanline[1] != 2 || scanline[2] & 128) {
171 scanline[0] = 2;
172 scanline[3] = i;
173 ret = decompress(scanline + 4, width - 1, &gb, scanline);
174 if (ret < 0)
175 return ret;
176 goto convert;
177 }
178
179 for (int i = 0; i < 4; i++) {
180 uint8_t *scanline = p->data[0] + y * p->linesize[0] + i;
181
182 for (int j = 0; j < width * 4 && bytestream2_get_bytes_left(&gb) > 0;) {
183 int run = bytestream2_get_byte(&gb);
184 if (run > 128) {
185 uint8_t val = bytestream2_get_byte(&gb);
186 run &= 127;
187 while (run--) {
188 if (j >= width * 4)
189 break;
190 scanline[j] = val;
191 j += 4;
192 }
193 } else if (run > 0) {
194 while (run--) {
195 if (j >= width * 4)
196 break;
197 scanline[j] = bytestream2_get_byte(&gb);
198 j += 4;
199 }
200 }
201 }
202 }
203
204convert:
205 for (int x = 0; x < width; x++) {
206 uint8_t rgbe[4];
207 int expo;
208
209 memcpy(rgbe, p->data[0] + y * p->linesize[0] + x * 4, 4);
210 expo = rgbe[3] - 128;
211
212 dst_r[x] = convert(expo, rgbe[0]);
213 dst_b[x] = convert(expo, rgbe[2]);
214 dst_g[x] = convert(expo, rgbe[1]);
215 }
216 }
217
218 *got_frame = 1;
219
220 return avpkt->size;
221}
222
224 .p.name = "hdr",
225 CODEC_LONG_NAME("HDR (Radiance RGBE format) image"),
226 .p.type = AVMEDIA_TYPE_VIDEO,
229 .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
231};
static double val(void *priv, double ch)
Definition aeval.c:77
const FFCodec ff_hdr_decoder
Definition hdrdec.c:223
Libavcodec external API header.
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition bytestream.h:168
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM
The decoder extracts and fills its parameters even if the frame is skipped due to the skip_frame sett...
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Definition utils.c:91
static void convert(float y, float u, float v, float *b, float *g, float *r)
Definition exr.c:968
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition codec.h:98
@ AV_CODEC_ID_RADIANCE_HDR
Definition codec_id.h:311
@ AVDISCARD_ALL
discard all
Definition defs.h:232
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
Definition rational.c:110
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static int hdr_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt)
Definition hdrdec.c:90
static int decompress(uint8_t *scanline, int w, GetByteContext *gb, const uint8_t *start)
Definition hdrdec.c:56
#define MAXELEN
Definition hdrdec.c:28
static float convert(int expo, int val)
Definition hdrdec.c:45
static int hdr_get_line(GetByteContext *gb, uint8_t *buffer, int size)
Definition hdrdec.c:30
Multithreading API for decoders.
#define ldexpf(x, exp)
Definition libm.h:391
uint8_t w
Definition llvidencdsp.c:39
#define AV_PIX_FMT_GBRPF32
Definition pixfmt.h:584
int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
Wrapper around get_buffer() for frame-multithreaded codecs.
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel.
Definition avcodec.h:628
enum AVDiscard skip_frame
Skip decoding for selected frames.
Definition avcodec.h:1667
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
uint8_t run
Definition svq3.c:207
static char buffer[20]
Definition seek.c:32
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
int size
static double c[64]