Browse code

DPX (Digital Picture Exchange) image decoder patch by Jimmy Christensen, jimmy ghost dk

Originally committed as revision 19163 to svn://svn.ffmpeg.org/ffmpeg/trunk

Jimmy Christensen authored on 2009/06/12 14:29:29
Showing 9 changed files
... ...
@@ -23,6 +23,7 @@ version <next>:
23 23
 - QCP demuxer
24 24
 - SoX native format muxer and demuxer
25 25
 - AMR-NB decoding/encoding, AMR-WB decoding via OpenCORE libraries
26
+- DPX image decoder
26 27
 
27 28
 
28 29
 
... ...
@@ -258,6 +258,8 @@ following image formats are supported:
258 258
     @tab Only uncompressed GIFs are generated.
259 259
 @item BMP          @tab X @tab X
260 260
     @tab Microsoft BMP image
261
+@item DPX          @tab   @tab X
262
+    @tab Digital Picture Exchange
261 263
 @item JPEG         @tab X @tab X
262 264
     @tab Progressive JPEG is not supported.
263 265
 @item JPEG 2000    @tab   @tab E
... ...
@@ -64,6 +64,7 @@ OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
64 64
 OBJS-$(CONFIG_DCA_DECODER)             += dca.o
65 65
 OBJS-$(CONFIG_DNXHD_DECODER)           += dnxhddec.o dnxhddata.o
66 66
 OBJS-$(CONFIG_DNXHD_ENCODER)           += dnxhdenc.o dnxhddata.o mpegvideo_enc.o motion_est.o ratecontrol.o mpeg12data.o mpegvideo.o
67
+OBJS-$(CONFIG_DPX_DECODER)             += dpx.o
67 68
 OBJS-$(CONFIG_DSICINAUDIO_DECODER)     += dsicinav.o
68 69
 OBJS-$(CONFIG_DSICINVIDEO_DECODER)     += dsicinav.o
69 70
 OBJS-$(CONFIG_DVBSUB_DECODER)          += dvbsubdec.o
... ...
@@ -76,6 +76,7 @@ void avcodec_register_all(void)
76 76
     REGISTER_DECODER (CSCD, cscd);
77 77
     REGISTER_DECODER (CYUV, cyuv);
78 78
     REGISTER_ENCDEC  (DNXHD, dnxhd);
79
+    REGISTER_DECODER (DPX, dpx);
79 80
     REGISTER_DECODER (DSICINVIDEO, dsicinvideo);
80 81
     REGISTER_ENCDEC  (DVVIDEO, dvvideo);
81 82
     REGISTER_DECODER (DXA, dxa);
... ...
@@ -196,6 +196,7 @@ enum CodecID {
196 196
     CODEC_ID_V210X,
197 197
     CODEC_ID_TMV,
198 198
     CODEC_ID_V210,
199
+    CODEC_ID_DPX,
199 200
 
200 201
     /* various PCM "codecs" */
201 202
     CODEC_ID_PCM_S16LE= 0x10000,
202 203
new file mode 100644
... ...
@@ -0,0 +1,228 @@
0
+/*
1
+ * DPX (.dpx) image decoder
2
+ * Copyright (c) 2009 Jimmy Christensen
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 "libavutil/intreadwrite.h"
22
+#include "bytestream.h"
23
+#include "avcodec.h"
24
+
25
+typedef struct DPXContext {
26
+    AVFrame picture;
27
+} DPXContext;
28
+
29
+
30
+static unsigned int read32(const uint8_t **ptr, int is_big)
31
+{
32
+    unsigned int temp;
33
+    if (is_big) {
34
+        temp = AV_RB32(*ptr);
35
+    } else {
36
+        temp = AV_RL32(*ptr);
37
+    }
38
+    *ptr += 4;
39
+    return temp;
40
+}
41
+
42
+static inline unsigned make_16bit(unsigned value)
43
+{
44
+    // mask away invalid bits
45
+    value &= 0xFFC0;
46
+    // correctly expand to 16 bits
47
+    return value + (value >> 10);
48
+}
49
+
50
+static int decode_frame(AVCodecContext *avctx,
51
+                        void *data,
52
+                        int *data_size,
53
+                        AVPacket *avpkt)
54
+{
55
+    const uint8_t *buf = avpkt->data;
56
+    int buf_size       = avpkt->size;
57
+    DPXContext *const s = avctx->priv_data;
58
+    AVFrame *picture  = data;
59
+    AVFrame *const p = &s->picture;
60
+    uint8_t *ptr;
61
+
62
+    int magic_num, offset, endian;
63
+    int x, y;
64
+    int w, h, stride, bits_per_color, descriptor, elements, target_packet_size, source_packet_size;
65
+
66
+    unsigned int rgbBuffer;
67
+
68
+    magic_num = AV_RB32(buf);
69
+    buf += 4;
70
+
71
+    /* Check if the files "magic number" is "SDPX" which means it uses
72
+     * big-endian or XPDS which is for little-endian files */
73
+    if (magic_num == AV_RL32("SDPX")) {
74
+        endian = 0;
75
+    } else if (magic_num == AV_RB32("SDPX")) {
76
+        endian = 1;
77
+    } else {
78
+        av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
79
+        return -1;
80
+    }
81
+
82
+    offset = read32(&buf, endian);
83
+    // Need to end in 0x304 offset from start of file
84
+    buf = avpkt->data + 0x304;
85
+    w = read32(&buf, endian);
86
+    h = read32(&buf, endian);
87
+
88
+    // Need to end in 0x320 to read the descriptor
89
+    buf += 20;
90
+    descriptor = buf[0];
91
+
92
+    // Need to end in 0x323 to read the bits per color
93
+    buf += 3;
94
+    bits_per_color = buf[0];
95
+
96
+    switch (descriptor) {
97
+        case 51: // RGBA
98
+            elements = 4;
99
+            break;
100
+        case 50: // RGB
101
+            elements = 3;
102
+            break;
103
+        default:
104
+            av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor);
105
+            return -1;
106
+    }
107
+
108
+    switch (bits_per_color) {
109
+        case 8:
110
+            if (elements == 4) {
111
+                avctx->pix_fmt = PIX_FMT_RGBA;
112
+            } else {
113
+                avctx->pix_fmt = PIX_FMT_RGB24;
114
+            }
115
+            source_packet_size = elements;
116
+            target_packet_size = elements;
117
+            break;
118
+        case 10:
119
+            avctx->pix_fmt = PIX_FMT_RGB48;
120
+            target_packet_size = 6;
121
+            source_packet_size = elements * 2;
122
+            break;
123
+        case 12:
124
+        case 16:
125
+            if (endian) {
126
+                avctx->pix_fmt = PIX_FMT_RGB48BE;
127
+            } else {
128
+                avctx->pix_fmt = PIX_FMT_RGB48LE;
129
+            }
130
+            target_packet_size = 6;
131
+            source_packet_size = elements * 2;
132
+            break;
133
+        default:
134
+            av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color);
135
+            return -1;
136
+    }
137
+
138
+    if (s->picture.data[0])
139
+        avctx->release_buffer(avctx, &s->picture);
140
+    if (avcodec_check_dimensions(avctx, w, h))
141
+        return -1;
142
+    if (w != avctx->width || h != avctx->height)
143
+        avcodec_set_dimensions(avctx, w, h);
144
+    if (avctx->get_buffer(avctx, p) < 0) {
145
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
146
+        return -1;
147
+    }
148
+
149
+    // Move pointer to offset from start of file
150
+    buf =  avpkt->data + offset;
151
+
152
+    ptr    = p->data[0];
153
+    stride = p->linesize[0];
154
+
155
+    switch (bits_per_color) {
156
+        case 10:
157
+            for (x = 0; x < avctx->height; x++) {
158
+               uint16_t *dst = (uint16_t*)ptr;
159
+               for (y = 0; y < avctx->width; y++) {
160
+                   rgbBuffer = read32(&buf, endian);
161
+                   // Read out the 10-bit colors and convert to 16-bit
162
+                   *dst++ = make_16bit(rgbBuffer >> 16);
163
+                   *dst++ = make_16bit(rgbBuffer >>  6);
164
+                   *dst++ = make_16bit(rgbBuffer <<  4);
165
+               }
166
+               ptr += stride;
167
+            }
168
+            break;
169
+        case 8:
170
+        case 12: // Treat 12-bit as 16-bit
171
+        case 16:
172
+            if (source_packet_size == target_packet_size) {
173
+                for (x = 0; x < avctx->height; x++) {
174
+                    memcpy(ptr, buf, target_packet_size*avctx->width);
175
+                    ptr += stride;
176
+                    buf += source_packet_size*avctx->width;
177
+                }
178
+            } else {
179
+                for (x = 0; x < avctx->height; x++) {
180
+                    uint8_t *dst = ptr;
181
+                    for (y = 0; y < avctx->width; y++) {
182
+                        memcpy(dst, buf, target_packet_size);
183
+                        dst += target_packet_size;
184
+                        buf += source_packet_size;
185
+                    }
186
+                    ptr += stride;
187
+                }
188
+            }
189
+            break;
190
+    }
191
+
192
+    *picture   = s->picture;
193
+    *data_size = sizeof(AVPicture);
194
+
195
+    return buf_size;
196
+}
197
+
198
+static av_cold int decode_init(AVCodecContext *avctx)
199
+{
200
+    DPXContext *s = avctx->priv_data;
201
+    avcodec_get_frame_defaults(&s->picture);
202
+    avctx->coded_frame = &s->picture;
203
+    return 0;
204
+}
205
+
206
+static av_cold int decode_end(AVCodecContext *avctx)
207
+{
208
+    DPXContext *s = avctx->priv_data;
209
+    if (s->picture.data[0])
210
+        avctx->release_buffer(avctx, &s->picture);
211
+
212
+    return 0;
213
+}
214
+
215
+AVCodec dpx_decoder = {
216
+    "dpx",
217
+    CODEC_TYPE_VIDEO,
218
+    CODEC_ID_DPX,
219
+    sizeof(DPXContext),
220
+    decode_init,
221
+    NULL,
222
+    decode_end,
223
+    decode_frame,
224
+    0,
225
+    NULL,
226
+    .long_name = NULL_IF_CONFIG_SMALL("DPX image"),
227
+};
... ...
@@ -72,6 +72,7 @@ static const IdStrMap img_tags[] = {
72 72
     { CODEC_ID_SUNRAST   , "im24"},
73 73
     { CODEC_ID_SUNRAST   , "sunras"},
74 74
     { CODEC_ID_JPEG2000  , "jp2"},
75
+    { CODEC_ID_DPX       , "dpx"},
75 76
     { CODEC_ID_NONE      , NULL}
76 77
 };
77 78
 
... ...
@@ -168,6 +168,7 @@ const AVCodecTag codec_movvideo_tags[] = {
168 168
     { CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') },
169 169
     { CODEC_ID_DNXHD, MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD */
170 170
     { CODEC_ID_SGI,   MKTAG('s', 'g', 'i', ' ') }, /* SGI  */
171
+    { CODEC_ID_DPX,   MKTAG('d', 'p', 'x', ' ') }, /* DPX */
171 172
 
172 173
     { CODEC_ID_NONE, 0 },
173 174
 };
... ...
@@ -212,6 +212,7 @@ const AVCodecTag codec_bmp_tags[] = {
212 212
     { CODEC_ID_SP5X,         MKTAG('S', 'P', '5', '4') },
213 213
     { CODEC_ID_AURA,         MKTAG('A', 'U', 'R', 'A') },
214 214
     { CODEC_ID_AURA2,        MKTAG('A', 'U', 'R', '2') },
215
+    { CODEC_ID_DPX,          MKTAG('d', 'p', 'x', ' ') },
215 216
     { CODEC_ID_NONE,         0 }
216 217
 };
217 218