00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00046 value &= 0xFFC0;
00047
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
00073
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
00085 buf = avpkt->data + 0x304;
00086 w = read32(&buf, endian);
00087 h = read32(&buf, endian);
00088
00089
00090 buf += 20;
00091 descriptor = buf[0];
00092
00093
00094 buf += 3;
00095 avctx->bits_per_raw_sample =
00096 bits_per_color = buf[0];
00097
00098 switch (descriptor) {
00099 case 51:
00100 elements = 4;
00101 break;
00102 case 50:
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
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
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:
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 };