]> git.sesse.net Git - ffmpeg/blob - libavcodec/dpx.c
avcodec/dpx: Read color information from DPX header
[ffmpeg] / libavcodec / dpx.c
1 /*
2  * DPX (.dpx) image decoder
3  * Copyright (c) 2009 Jimmy Christensen
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/avstring.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/intfloat.h"
25 #include "libavutil/imgutils.h"
26 #include "libavutil/timecode.h"
27 #include "bytestream.h"
28 #include "avcodec.h"
29 #include "internal.h"
30
31 enum DPX_TRC {
32     DPX_TRC_USER_DEFINED       = 0,
33     DPX_TRC_PRINTING_DENSITY   = 1,
34     DPX_TRC_LINEAR             = 2,
35     DPX_TRC_LOGARITHMIC        = 3,
36     DPX_TRC_UNSPECIFIED_VIDEO  = 4,
37     DPX_TRC_SMPTE_274          = 5,
38     DPX_TRC_ITU_R_709_4        = 6,
39     DPX_TRC_ITU_R_601_625      = 7,
40     DPX_TRC_ITU_R_601_525      = 8,
41     DPX_TRC_SMPTE_170          = 9,
42     DPX_TRC_ITU_R_624_4_PAL    = 10,
43     DPX_TRC_Z_LINEAR           = 11,
44     DPX_TRC_Z_HOMOGENEOUS      = 12,
45 };
46
47 enum DPX_COL_SPEC {
48     DPX_COL_SPEC_USER_DEFINED       = 0,
49     DPX_COL_SPEC_PRINTING_DENSITY   = 1,
50     /* 2 = N/A */
51     /* 3 = N/A */
52     DPX_COL_SPEC_UNSPECIFIED_VIDEO  = 4,
53     DPX_COL_SPEC_SMPTE_274          = 5,
54     DPX_COL_SPEC_ITU_R_709_4        = 6,
55     DPX_COL_SPEC_ITU_R_601_625      = 7,
56     DPX_COL_SPEC_ITU_R_601_525      = 8,
57     DPX_COL_SPEC_SMPTE_170          = 9,
58     DPX_COL_SPEC_ITU_R_624_4_PAL    = 10,
59     /* 11 = N/A */
60     /* 12 = N/A */
61 };
62
63 static unsigned int read16(const uint8_t **ptr, int is_big)
64 {
65     unsigned int temp;
66     if (is_big) {
67         temp = AV_RB16(*ptr);
68     } else {
69         temp = AV_RL16(*ptr);
70     }
71     *ptr += 2;
72     return temp;
73 }
74
75 static unsigned int read32(const uint8_t **ptr, int is_big)
76 {
77     unsigned int temp;
78     if (is_big) {
79         temp = AV_RB32(*ptr);
80     } else {
81         temp = AV_RL32(*ptr);
82     }
83     *ptr += 4;
84     return temp;
85 }
86
87 static uint16_t read10in32_gray(const uint8_t **ptr, uint32_t *lbuf,
88                                 int *n_datum, int is_big, int shift)
89 {
90     uint16_t temp;
91
92     if (*n_datum)
93         (*n_datum)--;
94     else {
95         *lbuf = read32(ptr, is_big);
96         *n_datum = 2;
97     }
98
99     temp = *lbuf >> shift & 0x3FF;
100     *lbuf = *lbuf >> 10;
101
102     return temp;
103 }
104
105 static uint16_t read10in32(const uint8_t **ptr, uint32_t *lbuf,
106                            int *n_datum, int is_big, int shift)
107 {
108     if (*n_datum)
109         (*n_datum)--;
110     else {
111         *lbuf = read32(ptr, is_big);
112         *n_datum = 2;
113     }
114
115     *lbuf = *lbuf << 10 | *lbuf >> shift & 0x3FFFFF;
116
117     return *lbuf & 0x3FF;
118 }
119
120 static uint16_t read12in32(const uint8_t **ptr, uint32_t *lbuf,
121                            int *n_datum, int is_big)
122 {
123     if (*n_datum)
124         (*n_datum)--;
125     else {
126         *lbuf = read32(ptr, is_big);
127         *n_datum = 7;
128     }
129
130     switch (*n_datum){
131     case 7: return *lbuf & 0xFFF;
132     case 6: return (*lbuf >> 12) & 0xFFF;
133     case 5: {
134             uint32_t c = *lbuf >> 24;
135             *lbuf = read32(ptr, is_big);
136             c |= *lbuf << 8;
137             return c & 0xFFF;
138             }
139     case 4: return (*lbuf >> 4) & 0xFFF;
140     case 3: return (*lbuf >> 16) & 0xFFF;
141     case 2: {
142             uint32_t c = *lbuf >> 28;
143             *lbuf = read32(ptr, is_big);
144             c |= *lbuf << 4;
145             return c & 0xFFF;
146             }
147     case 1: return (*lbuf >> 8) & 0xFFF;
148     default: return *lbuf >> 20;
149     }
150 }
151
152 static int decode_frame(AVCodecContext *avctx,
153                         void *data,
154                         int *got_frame,
155                         AVPacket *avpkt)
156 {
157     const uint8_t *buf = avpkt->data;
158     int buf_size       = avpkt->size;
159     AVFrame *const p = data;
160     uint8_t *ptr[AV_NUM_DATA_POINTERS];
161     uint32_t header_version, version = 0;
162     char creator[101];
163     char input_device[33];
164
165     unsigned int offset;
166     int magic_num, endian;
167     int x, y, stride, i, j, ret;
168     int w, h, bits_per_color, descriptor, elements, packing;
169     int yuv, color_trc, color_spec;
170     int encoding, need_align = 0;
171
172     unsigned int rgbBuffer = 0;
173     int n_datum = 0;
174
175     if (avpkt->size <= 1634) {
176         av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
177         return AVERROR_INVALIDDATA;
178     }
179
180     magic_num = AV_RB32(buf);
181     buf += 4;
182
183     /* Check if the files "magic number" is "SDPX" which means it uses
184      * big-endian or XPDS which is for little-endian files */
185     if (magic_num == AV_RL32("SDPX")) {
186         endian = 0;
187     } else if (magic_num == AV_RB32("SDPX")) {
188         endian = 1;
189     } else {
190         av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
191         return AVERROR_INVALIDDATA;
192     }
193
194     offset = read32(&buf, endian);
195     if (avpkt->size <= offset) {
196         av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
197         return AVERROR_INVALIDDATA;
198     }
199
200     header_version = read32(&buf, 0);
201     if (header_version == MKTAG('V','1','.','0'))
202         version = 1;
203     if (header_version == MKTAG('V','2','.','0'))
204         version = 2;
205     if (!version)
206         av_log(avctx, AV_LOG_WARNING, "Unknown header format version %s.\n",
207                av_fourcc2str(header_version));
208
209     // Check encryption
210     buf = avpkt->data + 660;
211     ret = read32(&buf, endian);
212     if (ret != 0xFFFFFFFF) {
213         avpriv_report_missing_feature(avctx, "Encryption");
214         av_log(avctx, AV_LOG_WARNING, "The image is encrypted and may "
215                "not properly decode.\n");
216     }
217
218     // Need to end in 0x304 offset from start of file
219     buf = avpkt->data + 0x304;
220     w = read32(&buf, endian);
221     h = read32(&buf, endian);
222
223     if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
224         return ret;
225
226     // Need to end in 0x320 to read the descriptor
227     buf += 20;
228     descriptor = buf[0];
229     color_trc = buf[1];
230     color_spec = buf[2];
231
232     // Need to end in 0x323 to read the bits per color
233     buf += 3;
234     avctx->bits_per_raw_sample =
235     bits_per_color = buf[0];
236     buf++;
237     packing = read16(&buf, endian);
238     encoding = read16(&buf, endian);
239
240     if (encoding) {
241         avpriv_report_missing_feature(avctx, "Encoding %d", encoding);
242         return AVERROR_PATCHWELCOME;
243     }
244
245     buf += 820;
246     avctx->sample_aspect_ratio.num = read32(&buf, endian);
247     avctx->sample_aspect_ratio.den = read32(&buf, endian);
248     if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
249         av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
250                    avctx->sample_aspect_ratio.num,  avctx->sample_aspect_ratio.den,
251                   0x10000);
252     else
253         avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
254
255     /* preferred frame rate from Motion-picture film header */
256     if (offset >= 1724 + 4) {
257         buf = avpkt->data + 1724;
258         i = read32(&buf, endian);
259         if(i && i != 0xFFFFFFFF) {
260             AVRational q = av_d2q(av_int2float(i), 4096);
261             if (q.num > 0 && q.den > 0)
262                 avctx->framerate = q;
263         }
264     }
265
266     /* alternative frame rate from television header */
267     if (offset >= 1940 + 4 &&
268         !(avctx->framerate.num && avctx->framerate.den)) {
269         buf = avpkt->data + 1940;
270         i = read32(&buf, endian);
271         if(i && i != 0xFFFFFFFF) {
272             AVRational q = av_d2q(av_int2float(i), 4096);
273             if (q.num > 0 && q.den > 0)
274                 avctx->framerate = q;
275         }
276     }
277
278     /* SMPTE TC from television header */
279     if (offset >= 1920 + 4) {
280         uint32_t tc;
281         uint32_t *tc_sd;
282         char tcbuf[AV_TIMECODE_STR_SIZE];
283
284         buf = avpkt->data + 1920;
285         // read32 to native endian, av_bswap32 to opposite of native for
286         // compatibility with av_timecode_make_smpte_tc_string2 etc
287         tc = av_bswap32(read32(&buf, endian));
288
289         if (i != 0xFFFFFFFF) {
290             AVFrameSideData *tcside =
291                 av_frame_new_side_data(p, AV_FRAME_DATA_S12M_TIMECODE,
292                                        sizeof(uint32_t) * 4);
293             if (!tcside)
294                 return AVERROR(ENOMEM);
295
296             tc_sd = (uint32_t*)tcside->data;
297             tc_sd[0] = 1;
298             tc_sd[1] = tc;
299
300             av_timecode_make_smpte_tc_string2(tcbuf, avctx->framerate,
301                                               tc_sd[1], 0, 0);
302             av_dict_set(&p->metadata, "timecode", tcbuf, 0);
303         }
304     }
305
306     /* color range from television header */
307     if (offset >= 1964 + 4) {
308         buf = avpkt->data + 1952;
309         i = read32(&buf, endian);
310
311         buf = avpkt->data + 1964;
312         j = read32(&buf, endian);
313
314         if (i != 0xFFFFFFFF && j != 0xFFFFFFFF) {
315             float minCV, maxCV;
316             minCV = av_int2float(i);
317             maxCV = av_int2float(j);
318             if (bits_per_color >= 1 &&
319                 minCV == 0.0f && maxCV == ((1<<bits_per_color) - 1)) {
320                 avctx->color_range = AVCOL_RANGE_JPEG;
321             } else if (bits_per_color >= 8 &&
322                        minCV == (1  <<(bits_per_color - 4)) &&
323                        maxCV == (235<<(bits_per_color - 8))) {
324                 avctx->color_range = AVCOL_RANGE_MPEG;
325             }
326         }
327     }
328
329     switch (descriptor) {
330     case 6:  // Y
331         elements = 1;
332         yuv = 1;
333         break;
334     case 50: // RGB
335         elements = 3;
336         break;
337     case 52: // ABGR
338     case 51: // RGBA
339         elements = 4;
340         break;
341     case 100: // UYVY422
342         elements = 2;
343         yuv = 1;
344         break;
345     case 102: // UYV444
346         elements = 3;
347         yuv = 1;
348         break;
349     case 103: // UYVA4444
350         elements = 4;
351         yuv = 1;
352         break;
353     default:
354         avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor);
355         return AVERROR_PATCHWELCOME;
356     }
357
358     switch (bits_per_color) {
359     case 8:
360         stride = avctx->width * elements;
361         break;
362     case 10:
363         if (!packing) {
364             av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
365             return -1;
366         }
367         stride = (avctx->width * elements + 2) / 3 * 4;
368         break;
369     case 12:
370         stride = avctx->width * elements;
371         if (packing) {
372             stride *= 2;
373         } else {
374             stride *= 3;
375             if (stride % 8) {
376                 stride /= 8;
377                 stride++;
378                 stride *= 8;
379             }
380             stride /= 2;
381         }
382         break;
383     case 16:
384         stride = 2 * avctx->width * elements;
385         break;
386     case 1:
387     case 32:
388     case 64:
389         avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color);
390         return AVERROR_PATCHWELCOME;
391     default:
392         return AVERROR_INVALIDDATA;
393     }
394
395     switch (color_trc) {
396     case DPX_TRC_LINEAR:
397         avctx->color_trc = AVCOL_TRC_LINEAR;
398         break;
399     case DPX_TRC_SMPTE_274:
400     case DPX_TRC_ITU_R_709_4:
401         avctx->color_trc = AVCOL_TRC_BT709;
402         break;
403     case DPX_TRC_ITU_R_601_625:
404     case DPX_TRC_ITU_R_601_525:
405     case DPX_TRC_SMPTE_170:
406         avctx->color_trc = AVCOL_TRC_SMPTE170M;
407         break;
408     case DPX_TRC_ITU_R_624_4_PAL:
409         avctx->color_trc = AVCOL_TRC_GAMMA28;
410         break;
411     case DPX_TRC_USER_DEFINED:
412     case DPX_TRC_UNSPECIFIED_VIDEO:
413         /* Nothing to do */
414         break;
415     default:
416         av_log(avctx, AV_LOG_VERBOSE, "Cannot map DPX transfer characteristic "
417             "%d to color_trc.\n", color_trc);
418         break;
419     }
420
421     switch (color_spec) {
422     case DPX_COL_SPEC_SMPTE_274:
423     case DPX_COL_SPEC_ITU_R_709_4:
424         avctx->color_primaries = AVCOL_PRI_BT709;
425         break;
426     case DPX_COL_SPEC_ITU_R_601_625:
427     case DPX_COL_SPEC_ITU_R_624_4_PAL:
428         avctx->color_primaries = AVCOL_PRI_BT470BG;
429         break;
430     case DPX_COL_SPEC_ITU_R_601_525:
431     case DPX_COL_SPEC_SMPTE_170:
432         avctx->color_primaries = AVCOL_PRI_SMPTE170M;
433         break;
434     case DPX_COL_SPEC_USER_DEFINED:
435     case DPX_COL_SPEC_UNSPECIFIED_VIDEO:
436         /* Nothing to do */
437         break;
438     default:
439         av_log(avctx, AV_LOG_VERBOSE, "Cannot map DPX color specification "
440             "%d to color_primaries.\n", color_spec);
441         break;
442     }
443
444     if (yuv) {
445         switch (color_spec) {
446         case DPX_COL_SPEC_SMPTE_274:
447         case DPX_COL_SPEC_ITU_R_709_4:
448             avctx->colorspace = AVCOL_SPC_BT709;
449             break;
450         case DPX_COL_SPEC_ITU_R_601_625:
451         case DPX_COL_SPEC_ITU_R_624_4_PAL:
452             avctx->colorspace = AVCOL_SPC_BT470BG;
453             break;
454         case DPX_COL_SPEC_ITU_R_601_525:
455         case DPX_COL_SPEC_SMPTE_170:
456             avctx->colorspace = AVCOL_SPC_SMPTE170M;
457             break;
458         case DPX_COL_SPEC_USER_DEFINED:
459         case DPX_COL_SPEC_UNSPECIFIED_VIDEO:
460             /* Nothing to do */
461             break;
462         default:
463             av_log(avctx, AV_LOG_INFO, "Cannot map DPX color specification "
464                 "%d to colorspace.\n", color_spec);
465             break;
466         }
467     } else {
468         avctx->colorspace = AVCOL_SPC_RGB;
469     }
470
471     // Table 3c: Runs will always break at scan line boundaries. Packing
472     // will always break to the next 32-bit word at scan-line boundaries.
473     // Unfortunately, the encoder produced invalid files, so attempt
474     // to detect it
475     need_align = FFALIGN(stride, 4);
476     if (need_align*avctx->height + (int64_t)offset > avpkt->size) {
477         // Alignment seems unappliable, try without
478         if (stride*avctx->height + (int64_t)offset > avpkt->size) {
479             av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
480             return AVERROR_INVALIDDATA;
481         } else {
482             av_log(avctx, AV_LOG_INFO, "Decoding DPX without scanline "
483                    "alignment.\n");
484             need_align = 0;
485         }
486     } else {
487         need_align -= stride;
488         stride = FFALIGN(stride, 4);
489     }
490
491     switch (1000 * descriptor + 10 * bits_per_color + endian) {
492     case 6081:
493     case 6080:
494         avctx->pix_fmt = AV_PIX_FMT_GRAY8;
495         break;
496     case 6121:
497     case 6120:
498         avctx->pix_fmt = AV_PIX_FMT_GRAY12;
499         break;
500     case 50081:
501     case 50080:
502         avctx->pix_fmt = AV_PIX_FMT_RGB24;
503         break;
504     case 52081:
505     case 52080:
506         avctx->pix_fmt = AV_PIX_FMT_ABGR;
507         break;
508     case 51081:
509     case 51080:
510         avctx->pix_fmt = AV_PIX_FMT_RGBA;
511         break;
512     case 50100:
513     case 50101:
514         avctx->pix_fmt = AV_PIX_FMT_GBRP10;
515         break;
516     case 51100:
517     case 51101:
518         avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
519         break;
520     case 50120:
521     case 50121:
522         avctx->pix_fmt = AV_PIX_FMT_GBRP12;
523         break;
524     case 51120:
525     case 51121:
526         avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
527         break;
528     case 6100:
529     case 6101:
530         avctx->pix_fmt = AV_PIX_FMT_GRAY10;
531         break;
532     case 6161:
533         avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
534         break;
535     case 6160:
536         avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
537         break;
538     case 50161:
539         avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
540         break;
541     case 50160:
542         avctx->pix_fmt = AV_PIX_FMT_RGB48LE;
543         break;
544     case 51161:
545         avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
546         break;
547     case 51160:
548         avctx->pix_fmt = AV_PIX_FMT_RGBA64LE;
549         break;
550     case 100081:
551         avctx->pix_fmt = AV_PIX_FMT_UYVY422;
552         break;
553     case 102081:
554         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
555         break;
556     case 103081:
557         avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
558         break;
559     default:
560         av_log(avctx, AV_LOG_ERROR, "Unsupported format\n");
561         return AVERROR_PATCHWELCOME;
562     }
563
564     ff_set_sar(avctx, avctx->sample_aspect_ratio);
565
566     if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
567         return ret;
568
569     av_strlcpy(creator, avpkt->data + 160, 100);
570     creator[100] = '\0';
571     av_dict_set(&p->metadata, "Creator", creator, 0);
572
573     av_strlcpy(input_device, avpkt->data + 1556, 32);
574     input_device[32] = '\0';
575     av_dict_set(&p->metadata, "Input Device", input_device, 0);
576
577     // Move pointer to offset from start of file
578     buf =  avpkt->data + offset;
579
580     for (i=0; i<AV_NUM_DATA_POINTERS; i++)
581         ptr[i] = p->data[i];
582
583     switch (bits_per_color) {
584     case 10:
585         for (x = 0; x < avctx->height; x++) {
586             uint16_t *dst[4] = {(uint16_t*)ptr[0],
587                                 (uint16_t*)ptr[1],
588                                 (uint16_t*)ptr[2],
589                                 (uint16_t*)ptr[3]};
590             int shift = elements > 1 ? packing == 1 ? 22 : 20 : packing == 1 ? 2 : 0;
591             for (y = 0; y < avctx->width; y++) {
592                 if (elements >= 3)
593                     *dst[2]++ = read10in32(&buf, &rgbBuffer,
594                                            &n_datum, endian, shift);
595                 if (elements == 1)
596                     *dst[0]++ = read10in32_gray(&buf, &rgbBuffer,
597                                                 &n_datum, endian, shift);
598                 else
599                     *dst[0]++ = read10in32(&buf, &rgbBuffer,
600                                            &n_datum, endian, shift);
601                 if (elements >= 2)
602                     *dst[1]++ = read10in32(&buf, &rgbBuffer,
603                                            &n_datum, endian, shift);
604                 if (elements == 4)
605                     *dst[3]++ =
606                     read10in32(&buf, &rgbBuffer,
607                                &n_datum, endian, shift);
608             }
609             if (memcmp(input_device, "Scanity", 7))
610                 n_datum = 0;
611             for (i = 0; i < elements; i++)
612                 ptr[i] += p->linesize[i];
613         }
614         break;
615     case 12:
616         for (x = 0; x < avctx->height; x++) {
617             uint16_t *dst[4] = {(uint16_t*)ptr[0],
618                                 (uint16_t*)ptr[1],
619                                 (uint16_t*)ptr[2],
620                                 (uint16_t*)ptr[3]};
621             int shift = packing == 1 ? 4 : 0;
622             for (y = 0; y < avctx->width; y++) {
623                 if (packing) {
624                     if (elements >= 3)
625                         *dst[2]++ = read16(&buf, endian) >> shift & 0xFFF;
626                     *dst[0]++ = read16(&buf, endian) >> shift & 0xFFF;
627                     if (elements >= 2)
628                         *dst[1]++ = read16(&buf, endian) >> shift & 0xFFF;
629                     if (elements == 4)
630                         *dst[3]++ = read16(&buf, endian) >> shift & 0xFFF;
631                 } else {
632                     if (elements >= 3)
633                         *dst[2]++ = read12in32(&buf, &rgbBuffer,
634                                                &n_datum, endian);
635                     *dst[0]++ = read12in32(&buf, &rgbBuffer,
636                                            &n_datum, endian);
637                     if (elements >= 2)
638                         *dst[1]++ = read12in32(&buf, &rgbBuffer,
639                                                &n_datum, endian);
640                     if (elements == 4)
641                         *dst[3]++ = read12in32(&buf, &rgbBuffer,
642                                                &n_datum, endian);
643                 }
644             }
645             n_datum = 0;
646             for (i = 0; i < elements; i++)
647                 ptr[i] += p->linesize[i];
648             // Jump to next aligned position
649             buf += need_align;
650         }
651         break;
652     case 16:
653         elements *= 2;
654     case 8:
655         if (   avctx->pix_fmt == AV_PIX_FMT_YUVA444P
656             || avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
657             for (x = 0; x < avctx->height; x++) {
658                 ptr[0] = p->data[0] + x * p->linesize[0];
659                 ptr[1] = p->data[1] + x * p->linesize[1];
660                 ptr[2] = p->data[2] + x * p->linesize[2];
661                 ptr[3] = p->data[3] + x * p->linesize[3];
662                 for (y = 0; y < avctx->width; y++) {
663                     *ptr[1]++ = *buf++;
664                     *ptr[0]++ = *buf++;
665                     *ptr[2]++ = *buf++;
666                     if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P)
667                         *ptr[3]++ = *buf++;
668                 }
669             }
670         } else {
671         av_image_copy_plane(ptr[0], p->linesize[0],
672                             buf, stride,
673                             elements * avctx->width, avctx->height);
674         }
675         break;
676     }
677
678     *got_frame = 1;
679
680     return buf_size;
681 }
682
683 AVCodec ff_dpx_decoder = {
684     .name           = "dpx",
685     .long_name      = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"),
686     .type           = AVMEDIA_TYPE_VIDEO,
687     .id             = AV_CODEC_ID_DPX,
688     .decode         = decode_frame,
689     .capabilities   = AV_CODEC_CAP_DR1,
690 };