blob: a5960334d58d33e57bda61b9924dfbc842cea6ef
1 | /* |
2 | * DPX (.dpx) image encoder |
3 | * Copyright (c) 2011 Peter Ross <pross@xvid.org> |
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/common.h" |
23 | #include "libavutil/intreadwrite.h" |
24 | #include "libavutil/imgutils.h" |
25 | #include "avcodec.h" |
26 | #include "internal.h" |
27 | |
28 | typedef struct DPXContext { |
29 | int big_endian; |
30 | int bits_per_component; |
31 | int num_components; |
32 | int descriptor; |
33 | int planar; |
34 | } DPXContext; |
35 | |
36 | static av_cold int encode_init(AVCodecContext *avctx) |
37 | { |
38 | DPXContext *s = avctx->priv_data; |
39 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); |
40 | |
41 | s->big_endian = !!(desc->flags & AV_PIX_FMT_FLAG_BE); |
42 | s->bits_per_component = desc->comp[0].depth; |
43 | s->num_components = desc->nb_components; |
44 | s->descriptor = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? 51 : 50; |
45 | s->planar = !!(desc->flags & AV_PIX_FMT_FLAG_PLANAR); |
46 | |
47 | switch (avctx->pix_fmt) { |
48 | case AV_PIX_FMT_ABGR: |
49 | s->descriptor = 52; |
50 | break; |
51 | case AV_PIX_FMT_GRAY16BE: |
52 | case AV_PIX_FMT_GRAY16LE: |
53 | case AV_PIX_FMT_GRAY8: |
54 | s->descriptor = 6; |
55 | break; |
56 | case AV_PIX_FMT_GBRP10BE: |
57 | case AV_PIX_FMT_GBRP10LE: |
58 | case AV_PIX_FMT_GBRP12BE: |
59 | case AV_PIX_FMT_GBRP12LE: |
60 | case AV_PIX_FMT_RGB24: |
61 | case AV_PIX_FMT_RGBA64BE: |
62 | case AV_PIX_FMT_RGBA64LE: |
63 | case AV_PIX_FMT_RGBA: |
64 | break; |
65 | case AV_PIX_FMT_RGB48LE: |
66 | case AV_PIX_FMT_RGB48BE: |
67 | if (avctx->bits_per_raw_sample) |
68 | s->bits_per_component = avctx->bits_per_raw_sample; |
69 | break; |
70 | default: |
71 | av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); |
72 | return -1; |
73 | } |
74 | |
75 | return 0; |
76 | } |
77 | |
78 | static av_always_inline void write16_internal(int big_endian, void *p, int value) |
79 | { |
80 | if (big_endian) AV_WB16(p, value); |
81 | else AV_WL16(p, value); |
82 | } |
83 | |
84 | static av_always_inline void write32_internal(int big_endian, void *p, int value) |
85 | { |
86 | if (big_endian) AV_WB32(p, value); |
87 | else AV_WL32(p, value); |
88 | } |
89 | |
90 | #define write16(p, value) write16_internal(s->big_endian, p, value) |
91 | #define write32(p, value) write32_internal(s->big_endian, p, value) |
92 | |
93 | static void encode_rgb48_10bit(AVCodecContext *avctx, const AVFrame *pic, |
94 | uint8_t *dst) |
95 | { |
96 | DPXContext *s = avctx->priv_data; |
97 | const uint8_t *src = pic->data[0]; |
98 | int x, y; |
99 | |
100 | for (y = 0; y < avctx->height; y++) { |
101 | for (x = 0; x < avctx->width; x++) { |
102 | int value; |
103 | if (s->big_endian) { |
104 | value = ((AV_RB16(src + 6*x + 4) & 0xFFC0U) >> 4) |
105 | | ((AV_RB16(src + 6*x + 2) & 0xFFC0U) << 6) |
106 | | ((AV_RB16(src + 6*x + 0) & 0xFFC0U) << 16); |
107 | } else { |
108 | value = ((AV_RL16(src + 6*x + 4) & 0xFFC0U) >> 4) |
109 | | ((AV_RL16(src + 6*x + 2) & 0xFFC0U) << 6) |
110 | | ((AV_RL16(src + 6*x + 0) & 0xFFC0U) << 16); |
111 | } |
112 | write32(dst, value); |
113 | dst += 4; |
114 | } |
115 | src += pic->linesize[0]; |
116 | } |
117 | } |
118 | |
119 | static void encode_gbrp10(AVCodecContext *avctx, const AVFrame *pic, uint8_t *dst) |
120 | { |
121 | DPXContext *s = avctx->priv_data; |
122 | const uint8_t *src[3] = {pic->data[0], pic->data[1], pic->data[2]}; |
123 | int x, y, i; |
124 | |
125 | for (y = 0; y < avctx->height; y++) { |
126 | for (x = 0; x < avctx->width; x++) { |
127 | int value; |
128 | if (s->big_endian) { |
129 | value = (AV_RB16(src[0] + 2*x) << 12) |
130 | | (AV_RB16(src[1] + 2*x) << 2) |
131 | | ((unsigned)AV_RB16(src[2] + 2*x) << 22); |
132 | } else { |
133 | value = (AV_RL16(src[0] + 2*x) << 12) |
134 | | (AV_RL16(src[1] + 2*x) << 2) |
135 | | ((unsigned)AV_RL16(src[2] + 2*x) << 22); |
136 | } |
137 | write32(dst, value); |
138 | dst += 4; |
139 | } |
140 | for (i = 0; i < 3; i++) |
141 | src[i] += pic->linesize[i]; |
142 | } |
143 | } |
144 | |
145 | static void encode_gbrp12(AVCodecContext *avctx, const AVFrame *pic, uint16_t *dst) |
146 | { |
147 | DPXContext *s = avctx->priv_data; |
148 | const uint16_t *src[3] = {(uint16_t*)pic->data[0], |
149 | (uint16_t*)pic->data[1], |
150 | (uint16_t*)pic->data[2]}; |
151 | int x, y, i, pad; |
152 | pad = avctx->width*6; |
153 | pad = (FFALIGN(pad, 4) - pad) >> 1; |
154 | for (y = 0; y < avctx->height; y++) { |
155 | for (x = 0; x < avctx->width; x++) { |
156 | uint16_t value[3]; |
157 | if (s->big_endian) { |
158 | value[1] = AV_RB16(src[0] + x) << 4; |
159 | value[2] = AV_RB16(src[1] + x) << 4; |
160 | value[0] = AV_RB16(src[2] + x) << 4; |
161 | } else { |
162 | value[1] = AV_RL16(src[0] + x) << 4; |
163 | value[2] = AV_RL16(src[1] + x) << 4; |
164 | value[0] = AV_RL16(src[2] + x) << 4; |
165 | } |
166 | for (i = 0; i < 3; i++) |
167 | write16(dst++, value[i]); |
168 | } |
169 | for (i = 0; i < pad; i++) |
170 | *dst++ = 0; |
171 | for (i = 0; i < 3; i++) |
172 | src[i] += pic->linesize[i]/2; |
173 | } |
174 | } |
175 | |
176 | static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
177 | const AVFrame *frame, int *got_packet) |
178 | { |
179 | DPXContext *s = avctx->priv_data; |
180 | int size, ret, need_align, len; |
181 | uint8_t *buf; |
182 | |
183 | #define HEADER_SIZE 1664 /* DPX Generic header */ |
184 | if (s->bits_per_component == 10) |
185 | size = avctx->height * avctx->width * 4; |
186 | else if (s->bits_per_component == 12) { |
187 | // 3 components, 12 bits put on 16 bits |
188 | len = avctx->width*6; |
189 | size = FFALIGN(len, 4); |
190 | need_align = size - len; |
191 | size *= avctx->height; |
192 | } else { |
193 | // N components, M bits |
194 | len = avctx->width * s->num_components * s->bits_per_component >> 3; |
195 | size = FFALIGN(len, 4); |
196 | need_align = size - len; |
197 | size *= avctx->height; |
198 | } |
199 | if ((ret = ff_alloc_packet2(avctx, pkt, size + HEADER_SIZE, 0)) < 0) |
200 | return ret; |
201 | buf = pkt->data; |
202 | |
203 | memset(buf, 0, HEADER_SIZE); |
204 | |
205 | /* File information header */ |
206 | write32(buf, MKBETAG('S','D','P','X')); |
207 | write32(buf + 4, HEADER_SIZE); |
208 | memcpy (buf + 8, "V1.0", 4); |
209 | write32(buf + 20, 1); /* new image */ |
210 | write32(buf + 24, HEADER_SIZE); |
211 | if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) |
212 | memcpy (buf + 160, LIBAVCODEC_IDENT, FFMIN(sizeof(LIBAVCODEC_IDENT), 100)); |
213 | write32(buf + 660, 0xFFFFFFFF); /* unencrypted */ |
214 | |
215 | /* Image information header */ |
216 | write16(buf + 768, 0); /* orientation; left to right, top to bottom */ |
217 | write16(buf + 770, 1); /* number of elements */ |
218 | write32(buf + 772, avctx->width); |
219 | write32(buf + 776, avctx->height); |
220 | buf[800] = s->descriptor; |
221 | buf[801] = 2; /* linear transfer */ |
222 | buf[802] = 2; /* linear colorimetric */ |
223 | buf[803] = s->bits_per_component; |
224 | write16(buf + 804, (s->bits_per_component == 10 || s->bits_per_component == 12) ? |
225 | 1 : 0); /* packing method */ |
226 | write32(buf + 808, HEADER_SIZE); /* data offset */ |
227 | |
228 | /* Image source information header */ |
229 | write32(buf + 1628, avctx->sample_aspect_ratio.num); |
230 | write32(buf + 1632, avctx->sample_aspect_ratio.den); |
231 | |
232 | switch(s->bits_per_component) { |
233 | case 8: |
234 | case 16: |
235 | if (need_align) { |
236 | int j; |
237 | const uint8_t *src = frame->data[0]; |
238 | uint8_t *dst = pkt->data + HEADER_SIZE; |
239 | size = (len + need_align) * avctx->height; |
240 | for (j=0; j<avctx->height; j++) { |
241 | memcpy(dst, src, len); |
242 | memset(dst + len, 0, need_align); |
243 | dst += len + need_align; |
244 | src += frame->linesize[0]; |
245 | } |
246 | } else { |
247 | size = av_image_copy_to_buffer(buf + HEADER_SIZE, pkt->size - HEADER_SIZE, |
248 | (const uint8_t**)frame->data, frame->linesize, |
249 | avctx->pix_fmt, |
250 | avctx->width, avctx->height, 1); |
251 | } |
252 | if (size < 0) |
253 | return size; |
254 | break; |
255 | case 10: |
256 | if (s->planar) |
257 | encode_gbrp10(avctx, frame, buf + HEADER_SIZE); |
258 | else |
259 | encode_rgb48_10bit(avctx, frame, buf + HEADER_SIZE); |
260 | break; |
261 | case 12: |
262 | encode_gbrp12(avctx, frame, (uint16_t*)(buf + HEADER_SIZE)); |
263 | break; |
264 | default: |
265 | av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", s->bits_per_component); |
266 | return -1; |
267 | } |
268 | |
269 | size += HEADER_SIZE; |
270 | |
271 | write32(buf + 16, size); /* file size */ |
272 | |
273 | pkt->flags |= AV_PKT_FLAG_KEY; |
274 | *got_packet = 1; |
275 | |
276 | return 0; |
277 | } |
278 | |
279 | AVCodec ff_dpx_encoder = { |
280 | .name = "dpx", |
281 | .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), |
282 | .type = AVMEDIA_TYPE_VIDEO, |
283 | .id = AV_CODEC_ID_DPX, |
284 | .priv_data_size = sizeof(DPXContext), |
285 | .init = encode_init, |
286 | .encode2 = encode_frame, |
287 | .pix_fmts = (const enum AVPixelFormat[]){ |
288 | AV_PIX_FMT_GRAY8, |
289 | AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_ABGR, |
290 | AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, |
291 | AV_PIX_FMT_RGB48LE, AV_PIX_FMT_RGB48BE, |
292 | AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_RGBA64BE, |
293 | AV_PIX_FMT_GBRP10LE, AV_PIX_FMT_GBRP10BE, |
294 | AV_PIX_FMT_GBRP12LE, AV_PIX_FMT_GBRP12BE, |
295 | AV_PIX_FMT_NONE}, |
296 | }; |
297 |