Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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/intreadwrite.h"
  23. #include "libavutil/imgutils.h"
  24. #include "bytestream.h"
  25. #include "avcodec.h"
  26. #include "internal.h"
  27.  
  28. static unsigned int read16(const uint8_t **ptr, int is_big)
  29. {
  30.     unsigned int temp;
  31.     if (is_big) {
  32.         temp = AV_RB16(*ptr);
  33.     } else {
  34.         temp = AV_RL16(*ptr);
  35.     }
  36.     *ptr += 2;
  37.     return temp;
  38. }
  39.  
  40. static unsigned int read32(const uint8_t **ptr, int is_big)
  41. {
  42.     unsigned int temp;
  43.     if (is_big) {
  44.         temp = AV_RB32(*ptr);
  45.     } else {
  46.         temp = AV_RL32(*ptr);
  47.     }
  48.     *ptr += 4;
  49.     return temp;
  50. }
  51.  
  52. static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf,
  53.                                   int * n_datum, int is_big)
  54. {
  55.     if (*n_datum)
  56.         (*n_datum)--;
  57.     else {
  58.         *lbuf = read32(ptr, is_big);
  59.         *n_datum = 2;
  60.     }
  61.  
  62.     *lbuf = (*lbuf << 10) | (*lbuf >> 22);
  63.  
  64.     return *lbuf & 0x3FF;
  65. }
  66.  
  67. static int decode_frame(AVCodecContext *avctx,
  68.                         void *data,
  69.                         int *got_frame,
  70.                         AVPacket *avpkt)
  71. {
  72.     const uint8_t *buf = avpkt->data;
  73.     int buf_size       = avpkt->size;
  74.     AVFrame *const p = data;
  75.     uint8_t *ptr[AV_NUM_DATA_POINTERS];
  76.  
  77.     unsigned int offset;
  78.     int magic_num, endian;
  79.     int x, y, i, ret;
  80.     int w, h, bits_per_color, descriptor, elements, packing, total_size;
  81.     int encoding;
  82.  
  83.     unsigned int rgbBuffer = 0;
  84.     int n_datum = 0;
  85.  
  86.     if (avpkt->size <= 1634) {
  87.         av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
  88.         return AVERROR_INVALIDDATA;
  89.     }
  90.  
  91.     magic_num = AV_RB32(buf);
  92.     buf += 4;
  93.  
  94.     /* Check if the files "magic number" is "SDPX" which means it uses
  95.      * big-endian or XPDS which is for little-endian files */
  96.     if (magic_num == AV_RL32("SDPX")) {
  97.         endian = 0;
  98.     } else if (magic_num == AV_RB32("SDPX")) {
  99.         endian = 1;
  100.     } else {
  101.         av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
  102.         return AVERROR_INVALIDDATA;
  103.     }
  104.  
  105.     offset = read32(&buf, endian);
  106.     if (avpkt->size <= offset) {
  107.         av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
  108.         return AVERROR_INVALIDDATA;
  109.     }
  110.     // Need to end in 0x304 offset from start of file
  111.     buf = avpkt->data + 0x304;
  112.     w = read32(&buf, endian);
  113.     h = read32(&buf, endian);
  114.     if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
  115.         return ret;
  116.  
  117.     if (w != avctx->width || h != avctx->height)
  118.         avcodec_set_dimensions(avctx, w, h);
  119.  
  120.     // Need to end in 0x320 to read the descriptor
  121.     buf += 20;
  122.     descriptor = buf[0];
  123.  
  124.     // Need to end in 0x323 to read the bits per color
  125.     buf += 3;
  126.     avctx->bits_per_raw_sample =
  127.     bits_per_color = buf[0];
  128.     buf++;
  129.     packing = read16(&buf, endian);
  130.     encoding = read16(&buf, endian);
  131.  
  132.     if (packing > 1) {
  133.         avpriv_report_missing_feature(avctx, "Packing %d", packing);
  134.         return AVERROR_PATCHWELCOME;
  135.     }
  136.     if (encoding) {
  137.         avpriv_report_missing_feature(avctx, "Encoding %d", encoding);
  138.         return AVERROR_PATCHWELCOME;
  139.     }
  140.  
  141.     buf += 820;
  142.     avctx->sample_aspect_ratio.num = read32(&buf, endian);
  143.     avctx->sample_aspect_ratio.den = read32(&buf, endian);
  144.     if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
  145.         av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
  146.                    avctx->sample_aspect_ratio.num,  avctx->sample_aspect_ratio.den,
  147.                   0x10000);
  148.     else
  149.         avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
  150.  
  151.     switch (descriptor) {
  152.     case 6:  // Y
  153.         elements = 1;
  154.         break;
  155.     case 52: // ABGR
  156.     case 51: // RGBA
  157.         elements = 4;
  158.         break;
  159.     case 50: // RGB
  160.         elements = 3;
  161.         break;
  162.     default:
  163.         avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor);
  164.         return AVERROR_PATCHWELCOME;
  165.     }
  166.  
  167.     switch (bits_per_color) {
  168.     case 8:
  169.         total_size = avctx->width * avctx->height * elements;
  170.         break;
  171.     case 10:
  172.         if (!packing) {
  173.             av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
  174.             return -1;
  175.         }
  176.         total_size = (avctx->width * elements + 2) / 3 * 4 * avctx->height;
  177.         break;
  178.     case 12:
  179.         if (!packing) {
  180.             av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n");
  181.             return -1;
  182.         }
  183.         total_size = 2 * avctx->width * avctx->height * elements;
  184.         break;
  185.     case 16:
  186.         total_size = 2 * avctx->width * avctx->height * elements;
  187.         break;
  188.     case 1:
  189.     case 32:
  190.     case 64:
  191.         avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color);
  192.         return AVERROR_PATCHWELCOME;
  193.     default:
  194.         return AVERROR_INVALIDDATA;
  195.     }
  196.  
  197.     switch (1000 * descriptor + 10 * bits_per_color + endian) {
  198.     case 6081:
  199.     case 6080:
  200.         avctx->pix_fmt = AV_PIX_FMT_GRAY8;
  201.         break;
  202.     case 50081:
  203.     case 50080:
  204.         avctx->pix_fmt = AV_PIX_FMT_RGB24;
  205.         break;
  206.     case 52081:
  207.     case 52080:
  208.         avctx->pix_fmt = AV_PIX_FMT_ABGR;
  209.         break;
  210.     case 51081:
  211.     case 51080:
  212.         avctx->pix_fmt = AV_PIX_FMT_RGBA;
  213.         break;
  214.     case 50100:
  215.     case 51100:
  216.     case 50101:
  217.     case 51101:
  218.         avctx->pix_fmt = AV_PIX_FMT_GBRP10;
  219.         break;
  220.     case 50120:
  221.     case 51120:
  222.     case 50121:
  223.     case 51121:
  224.         avctx->pix_fmt = AV_PIX_FMT_GBRP12;
  225.         break;
  226.     case 6161:
  227.         avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
  228.         break;
  229.     case 6160:
  230.         avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
  231.         break;
  232.     case 50161:
  233.         avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
  234.         break;
  235.     case 50160:
  236.         avctx->pix_fmt = AV_PIX_FMT_RGB48LE;
  237.         break;
  238.     case 51161:
  239.         avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
  240.         break;
  241.     case 51160:
  242.         avctx->pix_fmt = AV_PIX_FMT_RGBA64LE;
  243.         break;
  244.     default:
  245.         av_log(avctx, AV_LOG_ERROR, "Unsupported format\n");
  246.         return AVERROR_PATCHWELCOME;
  247.     }
  248.  
  249.     if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
  250.         return ret;
  251.  
  252.     // Move pointer to offset from start of file
  253.     buf =  avpkt->data + offset;
  254.  
  255.     for (i=0; i<AV_NUM_DATA_POINTERS; i++)
  256.         ptr[i] = p->data[i];
  257.  
  258.     if (total_size + (int64_t)offset > avpkt->size) {
  259.         av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
  260.         return AVERROR_INVALIDDATA;
  261.     }
  262.     switch (bits_per_color) {
  263.     case 10:
  264.         for (x = 0; x < avctx->height; x++) {
  265.             uint16_t *dst[3] = {(uint16_t*)ptr[0],
  266.                                 (uint16_t*)ptr[1],
  267.                                 (uint16_t*)ptr[2]};
  268.             for (y = 0; y < avctx->width; y++) {
  269.                 *dst[2]++ = read10in32(&buf, &rgbBuffer,
  270.                                        &n_datum, endian);
  271.                 *dst[0]++ = read10in32(&buf, &rgbBuffer,
  272.                                        &n_datum, endian);
  273.                 *dst[1]++ = read10in32(&buf, &rgbBuffer,
  274.                                        &n_datum, endian);
  275.                 // For 10 bit, ignore alpha
  276.                 if (elements == 4)
  277.                     read10in32(&buf, &rgbBuffer,
  278.                                &n_datum, endian);
  279.             }
  280.             n_datum = 0;
  281.             for (i = 0; i < 3; i++)
  282.                 ptr[i] += p->linesize[i];
  283.         }
  284.         break;
  285.     case 12:
  286.         for (x = 0; x < avctx->height; x++) {
  287.             uint16_t *dst[3] = {(uint16_t*)ptr[0],
  288.                                 (uint16_t*)ptr[1],
  289.                                 (uint16_t*)ptr[2]};
  290.             for (y = 0; y < avctx->width; y++) {
  291.                 *dst[2] = read16(&buf, endian) >> 4;
  292.                 dst[2]++;
  293.                 *dst[0] = read16(&buf, endian) >> 4;
  294.                 dst[0]++;
  295.                 *dst[1] = read16(&buf, endian) >> 4;
  296.                 dst[1]++;
  297.                 // For 12 bit, ignore alpha
  298.                 if (elements == 4)
  299.                     buf += 2;
  300.             }
  301.             for (i = 0; i < 3; i++)
  302.                 ptr[i] += p->linesize[i];
  303.         }
  304.         break;
  305.     case 16:
  306.         elements *= 2;
  307.     case 8:
  308.         av_image_copy_plane(ptr[0], p->linesize[0],
  309.                             buf, elements * avctx->width,
  310.                             elements * avctx->width, avctx->height);
  311.         break;
  312.     }
  313.  
  314.     *got_frame = 1;
  315.  
  316.     return buf_size;
  317. }
  318.  
  319. AVCodec ff_dpx_decoder = {
  320.     .name           = "dpx",
  321.     .long_name      = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"),
  322.     .type           = AVMEDIA_TYPE_VIDEO,
  323.     .id             = AV_CODEC_ID_DPX,
  324.     .decode         = decode_frame,
  325.     .capabilities   = CODEC_CAP_DR1,
  326. };
  327.