LCOV - code coverage report
Current view: top level - libavcodec - dpx.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 158 290 54.5 %
Date: 2018-05-20 11:54:08 Functions: 4 5 80.0 %

          Line data    Source code
       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/intfloat.h"
      24             : #include "libavutil/imgutils.h"
      25             : #include "bytestream.h"
      26             : #include "avcodec.h"
      27             : #include "internal.h"
      28             : 
      29     4257974 : static unsigned int read16(const uint8_t **ptr, int is_big)
      30             : {
      31             :     unsigned int temp;
      32     4257974 :     if (is_big) {
      33           4 :         temp = AV_RB16(*ptr);
      34             :     } else {
      35     4257970 :         temp = AV_RL16(*ptr);
      36             :     }
      37     4257974 :     *ptr += 2;
      38     4257974 :     return temp;
      39             : }
      40             : 
      41     2839076 : static unsigned int read32(const uint8_t **ptr, int is_big)
      42             : {
      43             :     unsigned int temp;
      44     2839076 :     if (is_big) {
      45          14 :         temp = AV_RB32(*ptr);
      46             :     } else {
      47     2839062 :         temp = AV_RL32(*ptr);
      48             :     }
      49     2839076 :     *ptr += 4;
      50     2839076 :     return temp;
      51             : }
      52             : 
      53     8515584 : static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf,
      54             :                                   int * n_datum, int is_big)
      55             : {
      56     8515584 :     if (*n_datum)
      57     5677056 :         (*n_datum)--;
      58             :     else {
      59     2838528 :         *lbuf = read32(ptr, is_big);
      60     2838528 :         *n_datum = 2;
      61             :     }
      62             : 
      63     8515584 :     *lbuf = (*lbuf << 10) | (*lbuf >> 22);
      64             : 
      65     8515584 :     return *lbuf & 0x3FF;
      66             : }
      67             : 
      68           0 : static uint16_t read12in32(const uint8_t **ptr, uint32_t * lbuf,
      69             :                                   int * n_datum, int is_big)
      70             : {
      71           0 :     if (*n_datum)
      72           0 :         (*n_datum)--;
      73             :     else {
      74           0 :         *lbuf = read32(ptr, is_big);
      75           0 :         *n_datum = 7;
      76             :     }
      77             : 
      78           0 :     switch (*n_datum){
      79           0 :     case 7: return *lbuf & 0xFFF;
      80           0 :     case 6: return (*lbuf >> 12) & 0xFFF;
      81           0 :     case 5: {
      82           0 :             uint32_t c = *lbuf >> 24;
      83           0 :             *lbuf = read32(ptr, is_big);
      84           0 :             c |= *lbuf << 8;
      85           0 :             return c & 0xFFF;
      86             :             }
      87           0 :     case 4: return (*lbuf >> 4) & 0xFFF;
      88           0 :     case 3: return (*lbuf >> 16) & 0xFFF;
      89           0 :     case 2: {
      90           0 :             uint32_t c = *lbuf >> 28;
      91           0 :             *lbuf = read32(ptr, is_big);
      92           0 :             c |= *lbuf << 4;
      93           0 :             return c & 0xFFF;
      94             :             }
      95           0 :     case 1: return (*lbuf >> 8) & 0xFFF;
      96           0 :     default: return *lbuf >> 20;
      97             :     }
      98             : }
      99             : 
     100          91 : static int decode_frame(AVCodecContext *avctx,
     101             :                         void *data,
     102             :                         int *got_frame,
     103             :                         AVPacket *avpkt)
     104             : {
     105          91 :     const uint8_t *buf = avpkt->data;
     106          91 :     int buf_size       = avpkt->size;
     107          91 :     AVFrame *const p = data;
     108             :     uint8_t *ptr[AV_NUM_DATA_POINTERS];
     109             : 
     110             :     unsigned int offset;
     111             :     int magic_num, endian;
     112             :     int x, y, stride, i, ret;
     113             :     int w, h, bits_per_color, descriptor, elements, packing;
     114          91 :     int encoding, need_align = 0;
     115             : 
     116          91 :     unsigned int rgbBuffer = 0;
     117          91 :     int n_datum = 0;
     118             : 
     119          91 :     if (avpkt->size <= 1634) {
     120           0 :         av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
     121           0 :         return AVERROR_INVALIDDATA;
     122             :     }
     123             : 
     124          91 :     magic_num = AV_RB32(buf);
     125          91 :     buf += 4;
     126             : 
     127             :     /* Check if the files "magic number" is "SDPX" which means it uses
     128             :      * big-endian or XPDS which is for little-endian files */
     129          91 :     if (magic_num == AV_RL32("SDPX")) {
     130          89 :         endian = 0;
     131           2 :     } else if (magic_num == AV_RB32("SDPX")) {
     132           2 :         endian = 1;
     133             :     } else {
     134           0 :         av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
     135           0 :         return AVERROR_INVALIDDATA;
     136             :     }
     137             : 
     138          91 :     offset = read32(&buf, endian);
     139          91 :     if (avpkt->size <= offset) {
     140           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
     141           0 :         return AVERROR_INVALIDDATA;
     142             :     }
     143             : 
     144             :     // Check encryption
     145          91 :     buf = avpkt->data + 660;
     146          91 :     ret = read32(&buf, endian);
     147          91 :     if (ret != 0xFFFFFFFF) {
     148           0 :         avpriv_report_missing_feature(avctx, "Encryption");
     149           0 :         av_log(avctx, AV_LOG_WARNING, "The image is encrypted and may "
     150             :                "not properly decode.\n");
     151             :     }
     152             : 
     153             :     // Need to end in 0x304 offset from start of file
     154          91 :     buf = avpkt->data + 0x304;
     155          91 :     w = read32(&buf, endian);
     156          91 :     h = read32(&buf, endian);
     157             : 
     158          91 :     if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
     159           0 :         return ret;
     160             : 
     161             :     // Need to end in 0x320 to read the descriptor
     162          91 :     buf += 20;
     163          91 :     descriptor = buf[0];
     164             : 
     165             :     // Need to end in 0x323 to read the bits per color
     166          91 :     buf += 3;
     167          91 :     avctx->bits_per_raw_sample =
     168          91 :     bits_per_color = buf[0];
     169          91 :     buf++;
     170          91 :     packing = read16(&buf, endian);
     171          91 :     encoding = read16(&buf, endian);
     172             : 
     173          91 :     if (packing > 1) {
     174           0 :         avpriv_report_missing_feature(avctx, "Packing %d", packing);
     175           0 :         return AVERROR_PATCHWELCOME;
     176             :     }
     177          91 :     if (encoding) {
     178           0 :         avpriv_report_missing_feature(avctx, "Encoding %d", encoding);
     179           0 :         return AVERROR_PATCHWELCOME;
     180             :     }
     181             : 
     182          91 :     buf += 820;
     183          91 :     avctx->sample_aspect_ratio.num = read32(&buf, endian);
     184          91 :     avctx->sample_aspect_ratio.den = read32(&buf, endian);
     185          91 :     if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
     186           0 :         av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
     187           0 :                    avctx->sample_aspect_ratio.num,  avctx->sample_aspect_ratio.den,
     188             :                   0x10000);
     189             :     else
     190          91 :         avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
     191             : 
     192          91 :     if (offset >= 1724 + 4) {
     193           2 :         buf = avpkt->data + 1724;
     194           2 :         i = read32(&buf, endian);
     195           2 :         if(i) {
     196           0 :             AVRational q = av_d2q(av_int2float(i), 4096);
     197           0 :             if (q.num > 0 && q.den > 0)
     198           0 :                 avctx->framerate = q;
     199             :         }
     200             :     }
     201             : 
     202          91 :     switch (descriptor) {
     203           0 :     case 6:  // Y
     204           0 :         elements = 1;
     205           0 :         break;
     206          14 :     case 52: // ABGR
     207             :     case 51: // RGBA
     208             :     case 103: // UYVA4444
     209          14 :         elements = 4;
     210          14 :         break;
     211          77 :     case 50: // RGB
     212             :     case 102: // UYV444
     213          77 :         elements = 3;
     214          77 :         break;
     215           0 :     case 100: // UYVY422
     216           0 :         elements = 2;
     217           0 :         break;
     218           0 :     default:
     219           0 :         avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor);
     220           0 :         return AVERROR_PATCHWELCOME;
     221             :     }
     222             : 
     223          91 :     switch (bits_per_color) {
     224          19 :     case 8:
     225          19 :         stride = avctx->width * elements;
     226          19 :         break;
     227          28 :     case 10:
     228          28 :         if (!packing) {
     229           0 :             av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
     230           0 :             return -1;
     231             :         }
     232          28 :         stride = (avctx->width * elements + 2) / 3 * 4;
     233          28 :         break;
     234          14 :     case 12:
     235          14 :         if (!packing) {
     236           0 :             int tested = 0;
     237           0 :             if (descriptor == 50 && endian && (avctx->width%8) == 0) { // Little endian and widths not a multiple of 8 need tests
     238           0 :                 tested = 1;
     239             :             }
     240           0 :             if (!tested) {
     241           0 :                 av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n");
     242           0 :                 return -1;
     243             :             }
     244             :         }
     245          14 :         stride = avctx->width * elements;
     246          14 :         if (packing) {
     247          14 :             stride *= 2;
     248             :         } else {
     249           0 :             stride *= 3;
     250           0 :             if (stride % 8) {
     251           0 :                 stride /= 8;
     252           0 :                 stride++;
     253           0 :                 stride *= 8;
     254             :             }
     255           0 :             stride /= 2;
     256             :         }
     257          14 :         break;
     258          30 :     case 16:
     259          30 :         stride = 2 * avctx->width * elements;
     260          30 :         break;
     261           0 :     case 1:
     262             :     case 32:
     263             :     case 64:
     264           0 :         avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color);
     265           0 :         return AVERROR_PATCHWELCOME;
     266           0 :     default:
     267           0 :         return AVERROR_INVALIDDATA;
     268             :     }
     269             : 
     270             :     // Table 3c: Runs will always break at scan line boundaries. Packing
     271             :     // will always break to the next 32-bit word at scan-line boundaries.
     272             :     // Unfortunately, the encoder produced invalid files, so attempt
     273             :     // to detect it
     274          91 :     need_align = FFALIGN(stride, 4);
     275          91 :     if (need_align*avctx->height + (int64_t)offset > avpkt->size) {
     276             :         // Alignment seems unappliable, try without
     277           0 :         if (stride*avctx->height + (int64_t)offset > avpkt->size) {
     278           0 :             av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
     279           0 :             return AVERROR_INVALIDDATA;
     280             :         } else {
     281           0 :             av_log(avctx, AV_LOG_INFO, "Decoding DPX without scanline "
     282             :                    "alignment.\n");
     283           0 :             need_align = 0;
     284             :         }
     285             :     } else {
     286          91 :         need_align -= stride;
     287          91 :         stride = FFALIGN(stride, 4);
     288             :     }
     289             : 
     290          91 :     switch (1000 * descriptor + 10 * bits_per_color + endian) {
     291           0 :     case 6081:
     292             :     case 6080:
     293           0 :         avctx->pix_fmt = AV_PIX_FMT_GRAY8;
     294           0 :         break;
     295           0 :     case 6121:
     296             :     case 6120:
     297           0 :         avctx->pix_fmt = AV_PIX_FMT_GRAY12;
     298           0 :         break;
     299          19 :     case 50081:
     300             :     case 50080:
     301          19 :         avctx->pix_fmt = AV_PIX_FMT_RGB24;
     302          19 :         break;
     303           0 :     case 52081:
     304             :     case 52080:
     305           0 :         avctx->pix_fmt = AV_PIX_FMT_ABGR;
     306           0 :         break;
     307           0 :     case 51081:
     308             :     case 51080:
     309           0 :         avctx->pix_fmt = AV_PIX_FMT_RGBA;
     310           0 :         break;
     311          28 :     case 50100:
     312             :     case 50101:
     313          28 :         avctx->pix_fmt = AV_PIX_FMT_GBRP10;
     314          28 :         break;
     315           0 :     case 51100:
     316             :     case 51101:
     317           0 :         avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
     318           0 :         break;
     319          14 :     case 50120:
     320             :     case 50121:
     321          14 :         avctx->pix_fmt = AV_PIX_FMT_GBRP12;
     322          14 :         break;
     323           0 :     case 51120:
     324             :     case 51121:
     325           0 :         avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
     326           0 :         break;
     327           0 :     case 6161:
     328           0 :         avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
     329           0 :         break;
     330           0 :     case 6160:
     331           0 :         avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
     332           0 :         break;
     333           2 :     case 50161:
     334           2 :         avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
     335           2 :         break;
     336          14 :     case 50160:
     337          14 :         avctx->pix_fmt = AV_PIX_FMT_RGB48LE;
     338          14 :         break;
     339           0 :     case 51161:
     340           0 :         avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
     341           0 :         break;
     342          14 :     case 51160:
     343          14 :         avctx->pix_fmt = AV_PIX_FMT_RGBA64LE;
     344          14 :         break;
     345           0 :     case 100081:
     346           0 :         avctx->pix_fmt = AV_PIX_FMT_UYVY422;
     347           0 :         break;
     348           0 :     case 102081:
     349           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
     350           0 :         break;
     351           0 :     case 103081:
     352           0 :         avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
     353           0 :         break;
     354           0 :     default:
     355           0 :         av_log(avctx, AV_LOG_ERROR, "Unsupported format\n");
     356           0 :         return AVERROR_PATCHWELCOME;
     357             :     }
     358             : 
     359          91 :     ff_set_sar(avctx, avctx->sample_aspect_ratio);
     360             : 
     361          91 :     if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
     362           0 :         return ret;
     363             : 
     364             :     // Move pointer to offset from start of file
     365          91 :     buf =  avpkt->data + offset;
     366             : 
     367         819 :     for (i=0; i<AV_NUM_DATA_POINTERS; i++)
     368         728 :         ptr[i] = p->data[i];
     369             : 
     370          91 :     switch (bits_per_color) {
     371          28 :     case 10:
     372        8092 :         for (x = 0; x < avctx->height; x++) {
     373       32256 :             uint16_t *dst[4] = {(uint16_t*)ptr[0],
     374        8064 :                                 (uint16_t*)ptr[1],
     375        8064 :                                 (uint16_t*)ptr[2],
     376        8064 :                                 (uint16_t*)ptr[3]};
     377     2846592 :             for (y = 0; y < avctx->width; y++) {
     378     2838528 :                 *dst[2]++ = read10in32(&buf, &rgbBuffer,
     379             :                                        &n_datum, endian);
     380     2838528 :                 *dst[0]++ = read10in32(&buf, &rgbBuffer,
     381             :                                        &n_datum, endian);
     382     2838528 :                 *dst[1]++ = read10in32(&buf, &rgbBuffer,
     383             :                                        &n_datum, endian);
     384     2838528 :                 if (elements == 4)
     385           0 :                     *dst[3]++ =
     386           0 :                     read10in32(&buf, &rgbBuffer,
     387             :                                &n_datum, endian);
     388             :             }
     389        8064 :             n_datum = 0;
     390       32256 :             for (i = 0; i < elements; i++)
     391       24192 :                 ptr[i] += p->linesize[i];
     392             :         }
     393          28 :         break;
     394          14 :     case 12:
     395        4046 :         for (x = 0; x < avctx->height; x++) {
     396       16128 :             uint16_t *dst[4] = {(uint16_t*)ptr[0],
     397        4032 :                                 (uint16_t*)ptr[1],
     398        4032 :                                 (uint16_t*)ptr[2],
     399        4032 :                                 (uint16_t*)ptr[3]};
     400     1423296 :             for (y = 0; y < avctx->width; y++) {
     401     1419264 :                 if (packing) {
     402     1419264 :                 if (elements >= 3)
     403     1419264 :                     *dst[2]++ = read16(&buf, endian) >> 4;
     404     1419264 :                 *dst[0] = read16(&buf, endian) >> 4;
     405     1419264 :                 dst[0]++;
     406     1419264 :                 if (elements >= 2)
     407     1419264 :                     *dst[1]++ = read16(&buf, endian) >> 4;
     408     1419264 :                 if (elements == 4)
     409           0 :                     *dst[3]++ = read16(&buf, endian) >> 4;
     410             :                 } else {
     411           0 :                     *dst[2]++ = read12in32(&buf, &rgbBuffer,
     412             :                                            &n_datum, endian);
     413           0 :                     *dst[0]++ = read12in32(&buf, &rgbBuffer,
     414             :                                            &n_datum, endian);
     415           0 :                     *dst[1]++ = read12in32(&buf, &rgbBuffer,
     416             :                                            &n_datum, endian);
     417           0 :                     if (elements == 4)
     418           0 :                         *dst[3]++ = read12in32(&buf, &rgbBuffer,
     419             :                                                &n_datum, endian);
     420             :                 }
     421             :             }
     422       16128 :             for (i = 0; i < elements; i++)
     423       12096 :                 ptr[i] += p->linesize[i];
     424             :             // Jump to next aligned position
     425        4032 :             buf += need_align;
     426             :         }
     427          14 :         break;
     428          30 :     case 16:
     429          30 :         elements *= 2;
     430          49 :     case 8:
     431          49 :         if (   avctx->pix_fmt == AV_PIX_FMT_YUVA444P
     432          49 :             || avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
     433           0 :             for (x = 0; x < avctx->height; x++) {
     434           0 :                 ptr[0] = p->data[0] + x * p->linesize[0];
     435           0 :                 ptr[1] = p->data[1] + x * p->linesize[1];
     436           0 :                 ptr[2] = p->data[2] + x * p->linesize[2];
     437           0 :                 ptr[3] = p->data[3] + x * p->linesize[3];
     438           0 :                 for (y = 0; y < avctx->width; y++) {
     439           0 :                     *ptr[1]++ = *buf++;
     440           0 :                     *ptr[0]++ = *buf++;
     441           0 :                     *ptr[2]++ = *buf++;
     442           0 :                     if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P)
     443           0 :                         *ptr[3]++ = *buf++;
     444             :                 }
     445             :             }
     446             :         } else {
     447          98 :         av_image_copy_plane(ptr[0], p->linesize[0],
     448             :                             buf, stride,
     449          49 :                             elements * avctx->width, avctx->height);
     450             :         }
     451          49 :         break;
     452             :     }
     453             : 
     454          91 :     *got_frame = 1;
     455             : 
     456          91 :     return buf_size;
     457             : }
     458             : 
     459             : AVCodec ff_dpx_decoder = {
     460             :     .name           = "dpx",
     461             :     .long_name      = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"),
     462             :     .type           = AVMEDIA_TYPE_VIDEO,
     463             :     .id             = AV_CODEC_ID_DPX,
     464             :     .decode         = decode_frame,
     465             :     .capabilities   = AV_CODEC_CAP_DR1,
     466             : };

Generated by: LCOV version 1.13