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 "libavutil/imgutils.h"
00024 #include "bytestream.h"
00025 #include "avcodec.h"
00026
00027 typedef struct DPXContext {
00028 AVFrame picture;
00029 } DPXContext;
00030
00031
00032 static unsigned int read32(const uint8_t **ptr, int is_big)
00033 {
00034 unsigned int temp;
00035 if (is_big) {
00036 temp = AV_RB32(*ptr);
00037 } else {
00038 temp = AV_RL32(*ptr);
00039 }
00040 *ptr += 4;
00041 return temp;
00042 }
00043
00044 static int decode_frame(AVCodecContext *avctx,
00045 void *data,
00046 int *data_size,
00047 AVPacket *avpkt)
00048 {
00049 const uint8_t *buf = avpkt->data;
00050 const uint8_t *buf_end = avpkt->data + avpkt->size;
00051 int buf_size = avpkt->size;
00052 DPXContext *const s = avctx->priv_data;
00053 AVFrame *picture = data;
00054 AVFrame *const p = &s->picture;
00055 uint8_t *ptr[AV_NUM_DATA_POINTERS];
00056
00057 unsigned int offset;
00058 int magic_num, endian;
00059 int x, y, i;
00060 int w, h, stride, bits_per_color, descriptor, elements, target_packet_size, source_packet_size;
00061 int planar;
00062
00063 unsigned int rgbBuffer;
00064
00065 if (avpkt->size <= 1634) {
00066 av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
00067 return AVERROR_INVALIDDATA;
00068 }
00069
00070 magic_num = AV_RB32(buf);
00071 buf += 4;
00072
00073
00074
00075 if (magic_num == AV_RL32("SDPX")) {
00076 endian = 0;
00077 } else if (magic_num == AV_RB32("SDPX")) {
00078 endian = 1;
00079 } else {
00080 av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
00081 return -1;
00082 }
00083
00084 offset = read32(&buf, endian);
00085 if (avpkt->size <= offset) {
00086 av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
00087 return AVERROR_INVALIDDATA;
00088 }
00089
00090 buf = avpkt->data + 0x304;
00091 w = read32(&buf, endian);
00092 h = read32(&buf, endian);
00093
00094
00095 buf += 20;
00096 descriptor = buf[0];
00097
00098
00099 buf += 3;
00100 avctx->bits_per_raw_sample =
00101 bits_per_color = buf[0];
00102
00103 buf += 825;
00104 avctx->sample_aspect_ratio.num = read32(&buf, endian);
00105 avctx->sample_aspect_ratio.den = read32(&buf, endian);
00106 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
00107 av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
00108 avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den,
00109 0x10000);
00110 else
00111 avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
00112
00113 switch (descriptor) {
00114 case 51:
00115 elements = 4;
00116 break;
00117 case 50:
00118 elements = 3;
00119 break;
00120 default:
00121 av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor);
00122 return -1;
00123 }
00124
00125 switch (bits_per_color) {
00126 case 8:
00127 if (elements == 4) {
00128 avctx->pix_fmt = PIX_FMT_RGBA;
00129 } else {
00130 avctx->pix_fmt = PIX_FMT_RGB24;
00131 }
00132 source_packet_size = elements;
00133 target_packet_size = elements;
00134 planar = 0;
00135 break;
00136 case 10:
00137 avctx->pix_fmt = PIX_FMT_GBRP10;
00138 target_packet_size = 6;
00139 source_packet_size = 4;
00140 planar = 1;
00141 break;
00142 case 12:
00143 if (endian) {
00144 avctx->pix_fmt = elements == 4 ? PIX_FMT_GBRP12BE : PIX_FMT_GBRP12BE;
00145 } else {
00146 avctx->pix_fmt = elements == 4 ? PIX_FMT_GBRP12LE : PIX_FMT_GBRP12LE;
00147 }
00148 target_packet_size = 6;
00149 source_packet_size = 6;
00150 planar = 1;
00151 break;
00152 case 16:
00153 if (endian) {
00154 avctx->pix_fmt = elements == 4 ? PIX_FMT_RGBA64BE : PIX_FMT_RGB48BE;
00155 } else {
00156 avctx->pix_fmt = elements == 4 ? PIX_FMT_RGBA64LE : PIX_FMT_RGB48LE;
00157 }
00158 target_packet_size =
00159 source_packet_size = elements * 2;
00160 planar = 0;
00161 break;
00162 default:
00163 av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color);
00164 return -1;
00165 }
00166
00167 if (s->picture.data[0])
00168 avctx->release_buffer(avctx, &s->picture);
00169 if (av_image_check_size(w, h, 0, avctx))
00170 return -1;
00171 if (w != avctx->width || h != avctx->height)
00172 avcodec_set_dimensions(avctx, w, h);
00173 if (avctx->get_buffer(avctx, p) < 0) {
00174 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00175 return -1;
00176 }
00177
00178
00179 buf = avpkt->data + offset;
00180
00181 for (i=0; i<AV_NUM_DATA_POINTERS; i++)
00182 ptr[i] = p->data[i];
00183 stride = p->linesize[0];
00184
00185 if (source_packet_size*avctx->width*avctx->height > buf_end - buf) {
00186 av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
00187 return -1;
00188 }
00189 switch (bits_per_color) {
00190 case 10:
00191 for (x = 0; x < avctx->height; x++) {
00192 uint16_t *dst[3] = {(uint16_t*)ptr[0],
00193 (uint16_t*)ptr[1],
00194 (uint16_t*)ptr[2]};
00195 for (y = 0; y < avctx->width; y++) {
00196 rgbBuffer = read32(&buf, endian);
00197 *dst[0]++ = (rgbBuffer >> 12) & 0x3FF;
00198 *dst[1]++ = (rgbBuffer >> 2) & 0x3FF;
00199 *dst[2]++ = (rgbBuffer >> 22) & 0x3FF;
00200 }
00201 for (i=0; i<3; i++)
00202 ptr[i] += p->linesize[i];
00203 }
00204 break;
00205 case 8:
00206 case 12:
00207 case 16:
00208 if (planar) {
00209 int source_bpc = target_packet_size / elements;
00210 int target_bpc = target_packet_size / elements;
00211 for (x = 0; x < avctx->height; x++) {
00212 uint8_t *dst[AV_NUM_DATA_POINTERS];
00213 for (i=0; i<elements; i++)
00214 dst[i] = ptr[i];
00215 for (y = 0; y < avctx->width; y++) {
00216 for (i=0; i<3; i++) {
00217 memcpy(dst[i], buf, FFMIN(source_bpc, target_bpc));
00218 dst[i] += target_bpc;
00219 buf += source_bpc;
00220 }
00221 }
00222 for (i=0; i<elements; i++)
00223 ptr[i] += p->linesize[i];
00224 }
00225 } else {
00226 if (source_packet_size == target_packet_size) {
00227 for (x = 0; x < avctx->height; x++) {
00228 memcpy(ptr[0], buf, target_packet_size*avctx->width);
00229 ptr[0] += stride;
00230 buf += source_packet_size*avctx->width;
00231 }
00232 } else {
00233 for (x = 0; x < avctx->height; x++) {
00234 uint8_t *dst = ptr[0];
00235 for (y = 0; y < avctx->width; y++) {
00236 memcpy(dst, buf, target_packet_size);
00237 dst += target_packet_size;
00238 buf += source_packet_size;
00239 }
00240 ptr[0] += stride;
00241 }
00242 }
00243 }
00244 break;
00245 }
00246
00247 *picture = s->picture;
00248 *data_size = sizeof(AVPicture);
00249
00250 return buf_size;
00251 }
00252
00253 static av_cold int decode_init(AVCodecContext *avctx)
00254 {
00255 DPXContext *s = avctx->priv_data;
00256 avcodec_get_frame_defaults(&s->picture);
00257 avctx->coded_frame = &s->picture;
00258 return 0;
00259 }
00260
00261 static av_cold int decode_end(AVCodecContext *avctx)
00262 {
00263 DPXContext *s = avctx->priv_data;
00264 if (s->picture.data[0])
00265 avctx->release_buffer(avctx, &s->picture);
00266
00267 return 0;
00268 }
00269
00270 AVCodec ff_dpx_decoder = {
00271 .name = "dpx",
00272 .type = AVMEDIA_TYPE_VIDEO,
00273 .id = AV_CODEC_ID_DPX,
00274 .priv_data_size = sizeof(DPXContext),
00275 .init = decode_init,
00276 .close = decode_end,
00277 .decode = decode_frame,
00278 .capabilities = CODEC_CAP_DR1,
00279 .long_name = NULL_IF_CONFIG_SMALL("DPX image"),
00280 };