• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/dpx.c

Go to the documentation of this file.
00001 /*
00002  * DPX (.dpx) image decoder
00003  * Copyright (c) 2009 Jimmy Christensen
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/intreadwrite.h"
00023 #include "bytestream.h"
00024 #include "avcodec.h"
00025 
00026 typedef struct DPXContext {
00027     AVFrame picture;
00028 } DPXContext;
00029 
00030 
00031 static unsigned int read32(const uint8_t **ptr, int is_big)
00032 {
00033     unsigned int temp;
00034     if (is_big) {
00035         temp = AV_RB32(*ptr);
00036     } else {
00037         temp = AV_RL32(*ptr);
00038     }
00039     *ptr += 4;
00040     return temp;
00041 }
00042 
00043 static inline unsigned make_16bit(unsigned value)
00044 {
00045     // mask away invalid bits
00046     value &= 0xFFC0;
00047     // correctly expand to 16 bits
00048     return value + (value >> 10);
00049 }
00050 
00051 static int decode_frame(AVCodecContext *avctx,
00052                         void *data,
00053                         int *data_size,
00054                         AVPacket *avpkt)
00055 {
00056     const uint8_t *buf = avpkt->data;
00057     int buf_size       = avpkt->size;
00058     DPXContext *const s = avctx->priv_data;
00059     AVFrame *picture  = data;
00060     AVFrame *const p = &s->picture;
00061     uint8_t *ptr;
00062 
00063     int magic_num, offset, endian;
00064     int x, y;
00065     int w, h, stride, bits_per_color, descriptor, elements, target_packet_size, source_packet_size;
00066 
00067     unsigned int rgbBuffer;
00068 
00069     magic_num = AV_RB32(buf);
00070     buf += 4;
00071 
00072     /* Check if the files "magic number" is "SDPX" which means it uses
00073      * big-endian or XPDS which is for little-endian files */
00074     if (magic_num == AV_RL32("SDPX")) {
00075         endian = 0;
00076     } else if (magic_num == AV_RB32("SDPX")) {
00077         endian = 1;
00078     } else {
00079         av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
00080         return -1;
00081     }
00082 
00083     offset = read32(&buf, endian);
00084     // Need to end in 0x304 offset from start of file
00085     buf = avpkt->data + 0x304;
00086     w = read32(&buf, endian);
00087     h = read32(&buf, endian);
00088 
00089     // Need to end in 0x320 to read the descriptor
00090     buf += 20;
00091     descriptor = buf[0];
00092 
00093     // Need to end in 0x323 to read the bits per color
00094     buf += 3;
00095     avctx->bits_per_raw_sample =
00096     bits_per_color = buf[0];
00097 
00098     switch (descriptor) {
00099         case 51: // RGBA
00100             elements = 4;
00101             break;
00102         case 50: // RGB
00103             elements = 3;
00104             break;
00105         default:
00106             av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor);
00107             return -1;
00108     }
00109 
00110     switch (bits_per_color) {
00111         case 8:
00112             if (elements == 4) {
00113                 avctx->pix_fmt = PIX_FMT_RGBA;
00114             } else {
00115                 avctx->pix_fmt = PIX_FMT_RGB24;
00116             }
00117             source_packet_size = elements;
00118             target_packet_size = elements;
00119             break;
00120         case 10:
00121             avctx->pix_fmt = PIX_FMT_RGB48;
00122             target_packet_size = 6;
00123             source_packet_size = elements * 2;
00124             break;
00125         case 12:
00126         case 16:
00127             if (endian) {
00128                 avctx->pix_fmt = PIX_FMT_RGB48BE;
00129             } else {
00130                 avctx->pix_fmt = PIX_FMT_RGB48LE;
00131             }
00132             target_packet_size = 6;
00133             source_packet_size = elements * 2;
00134             break;
00135         default:
00136             av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color);
00137             return -1;
00138     }
00139 
00140     if (s->picture.data[0])
00141         avctx->release_buffer(avctx, &s->picture);
00142     if (avcodec_check_dimensions(avctx, w, h))
00143         return -1;
00144     if (w != avctx->width || h != avctx->height)
00145         avcodec_set_dimensions(avctx, w, h);
00146     if (avctx->get_buffer(avctx, p) < 0) {
00147         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00148         return -1;
00149     }
00150 
00151     // Move pointer to offset from start of file
00152     buf =  avpkt->data + offset;
00153 
00154     ptr    = p->data[0];
00155     stride = p->linesize[0];
00156 
00157     switch (bits_per_color) {
00158         case 10:
00159             for (x = 0; x < avctx->height; x++) {
00160                uint16_t *dst = (uint16_t*)ptr;
00161                for (y = 0; y < avctx->width; y++) {
00162                    rgbBuffer = read32(&buf, endian);
00163                    // Read out the 10-bit colors and convert to 16-bit
00164                    *dst++ = make_16bit(rgbBuffer >> 16);
00165                    *dst++ = make_16bit(rgbBuffer >>  6);
00166                    *dst++ = make_16bit(rgbBuffer <<  4);
00167                }
00168                ptr += stride;
00169             }
00170             break;
00171         case 8:
00172         case 12: // Treat 12-bit as 16-bit
00173         case 16:
00174             if (source_packet_size == target_packet_size) {
00175                 for (x = 0; x < avctx->height; x++) {
00176                     memcpy(ptr, buf, target_packet_size*avctx->width);
00177                     ptr += stride;
00178                     buf += source_packet_size*avctx->width;
00179                 }
00180             } else {
00181                 for (x = 0; x < avctx->height; x++) {
00182                     uint8_t *dst = ptr;
00183                     for (y = 0; y < avctx->width; y++) {
00184                         memcpy(dst, buf, target_packet_size);
00185                         dst += target_packet_size;
00186                         buf += source_packet_size;
00187                     }
00188                     ptr += stride;
00189                 }
00190             }
00191             break;
00192     }
00193 
00194     *picture   = s->picture;
00195     *data_size = sizeof(AVPicture);
00196 
00197     return buf_size;
00198 }
00199 
00200 static av_cold int decode_init(AVCodecContext *avctx)
00201 {
00202     DPXContext *s = avctx->priv_data;
00203     avcodec_get_frame_defaults(&s->picture);
00204     avctx->coded_frame = &s->picture;
00205     return 0;
00206 }
00207 
00208 static av_cold int decode_end(AVCodecContext *avctx)
00209 {
00210     DPXContext *s = avctx->priv_data;
00211     if (s->picture.data[0])
00212         avctx->release_buffer(avctx, &s->picture);
00213 
00214     return 0;
00215 }
00216 
00217 AVCodec dpx_decoder = {
00218     "dpx",
00219     AVMEDIA_TYPE_VIDEO,
00220     CODEC_ID_DPX,
00221     sizeof(DPXContext),
00222     decode_init,
00223     NULL,
00224     decode_end,
00225     decode_frame,
00226     0,
00227     NULL,
00228     .long_name = NULL_IF_CONFIG_SMALL("DPX image"),
00229 };

Generated on Fri Sep 16 2011 17:17:35 for FFmpeg by  doxygen 1.7.1