2 * DPX (.dpx) image decoder
3 * Copyright (c) 2009 Jimmy Christensen
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/intreadwrite.h"
23 #include "bytestream.h"
26 typedef struct DPXContext
{
31 static unsigned int read32(const uint8_t **ptr
, int is_big
)
43 static inline unsigned make_16bit(unsigned value
)
45 // mask away invalid bits
47 // correctly expand to 16 bits
48 return value
+ (value
>> 10);
51 static int decode_frame(AVCodecContext
*avctx
,
56 const uint8_t *buf
= avpkt
->data
;
57 int buf_size
= avpkt
->size
;
58 DPXContext
*const s
= avctx
->priv_data
;
59 AVFrame
*picture
= data
;
60 AVFrame
*const p
= &s
->picture
;
63 int magic_num
, offset
, endian
;
65 int w
, h
, stride
, bits_per_color
, descriptor
, elements
, target_packet_size
, source_packet_size
;
67 unsigned int rgbBuffer
;
69 magic_num
= AV_RB32(buf
);
72 /* Check if the files "magic number" is "SDPX" which means it uses
73 * big-endian or XPDS which is for little-endian files */
74 if (magic_num
== AV_RL32("SDPX")) {
76 } else if (magic_num
== AV_RB32("SDPX")) {
79 av_log(avctx
, AV_LOG_ERROR
, "DPX marker not found\n");
83 offset
= read32(&buf
, endian
);
84 // Need to end in 0x304 offset from start of file
85 buf
= avpkt
->data
+ 0x304;
86 w
= read32(&buf
, endian
);
87 h
= read32(&buf
, endian
);
89 // Need to end in 0x320 to read the descriptor
93 // Need to end in 0x323 to read the bits per color
95 bits_per_color
= buf
[0];
105 av_log(avctx
, AV_LOG_ERROR
, "Unsupported descriptor %d\n", descriptor
);
109 switch (bits_per_color
) {
112 avctx
->pix_fmt
= PIX_FMT_RGBA
;
114 avctx
->pix_fmt
= PIX_FMT_RGB24
;
116 source_packet_size
= elements
;
117 target_packet_size
= elements
;
120 avctx
->pix_fmt
= PIX_FMT_RGB48
;
121 target_packet_size
= 6;
122 source_packet_size
= elements
* 2;
127 avctx
->pix_fmt
= PIX_FMT_RGB48BE
;
129 avctx
->pix_fmt
= PIX_FMT_RGB48LE
;
131 target_packet_size
= 6;
132 source_packet_size
= elements
* 2;
135 av_log(avctx
, AV_LOG_ERROR
, "Unsupported color depth : %d\n", bits_per_color
);
139 if (s
->picture
.data
[0])
140 avctx
->release_buffer(avctx
, &s
->picture
);
141 if (avcodec_check_dimensions(avctx
, w
, h
))
143 if (w
!= avctx
->width
|| h
!= avctx
->height
)
144 avcodec_set_dimensions(avctx
, w
, h
);
145 if (avctx
->get_buffer(avctx
, p
) < 0) {
146 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
150 // Move pointer to offset from start of file
151 buf
= avpkt
->data
+ offset
;
154 stride
= p
->linesize
[0];
156 switch (bits_per_color
) {
158 for (x
= 0; x
< avctx
->height
; x
++) {
159 uint16_t *dst
= (uint16_t*)ptr
;
160 for (y
= 0; y
< avctx
->width
; y
++) {
161 rgbBuffer
= read32(&buf
, endian
);
162 // Read out the 10-bit colors and convert to 16-bit
163 *dst
++ = make_16bit(rgbBuffer
>> 16);
164 *dst
++ = make_16bit(rgbBuffer
>> 6);
165 *dst
++ = make_16bit(rgbBuffer
<< 4);
171 case 12: // Treat 12-bit as 16-bit
173 if (source_packet_size
== target_packet_size
) {
174 for (x
= 0; x
< avctx
->height
; x
++) {
175 memcpy(ptr
, buf
, target_packet_size
*avctx
->width
);
177 buf
+= source_packet_size
*avctx
->width
;
180 for (x
= 0; x
< avctx
->height
; x
++) {
182 for (y
= 0; y
< avctx
->width
; y
++) {
183 memcpy(dst
, buf
, target_packet_size
);
184 dst
+= target_packet_size
;
185 buf
+= source_packet_size
;
193 *picture
= s
->picture
;
194 *data_size
= sizeof(AVPicture
);
199 static av_cold
int decode_init(AVCodecContext
*avctx
)
201 DPXContext
*s
= avctx
->priv_data
;
202 avcodec_get_frame_defaults(&s
->picture
);
203 avctx
->coded_frame
= &s
->picture
;
207 static av_cold
int decode_end(AVCodecContext
*avctx
)
209 DPXContext
*s
= avctx
->priv_data
;
210 if (s
->picture
.data
[0])
211 avctx
->release_buffer(avctx
, &s
->picture
);
216 AVCodec dpx_decoder
= {
227 .long_name
= NULL_IF_CONFIG_SMALL("DPX image"),