Libav 0.7.1
|
00001 /* 00002 * DPX (.dpx) image encoder 00003 * Copyright (c) 2011 Peter Ross <pross@xvid.org> 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; 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 "libavutil/imgutils.h" 00024 #include "avcodec.h" 00025 00026 typedef struct DPXContext { 00027 AVFrame picture; 00028 int big_endian; 00029 int bits_per_component; 00030 int descriptor; 00031 } DPXContext; 00032 00033 static av_cold int encode_init(AVCodecContext *avctx) 00034 { 00035 DPXContext *s = avctx->priv_data; 00036 00037 avctx->coded_frame = &s->picture; 00038 avctx->coded_frame->pict_type = FF_I_TYPE; 00039 avctx->coded_frame->key_frame = 1; 00040 00041 s->big_endian = 1; 00042 s->bits_per_component = 8; 00043 s->descriptor = 50; /* RGB */ 00044 00045 switch (avctx->pix_fmt) { 00046 case PIX_FMT_RGB24: 00047 break; 00048 case PIX_FMT_RGBA: 00049 s->descriptor = 51; /* RGBA */ 00050 break; 00051 case PIX_FMT_RGB48LE: 00052 s->big_endian = 0; 00053 case PIX_FMT_RGB48BE: 00054 s->bits_per_component = avctx->bits_per_raw_sample ? avctx->bits_per_raw_sample : 16; 00055 break; 00056 default: 00057 av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); 00058 return -1; 00059 } 00060 00061 return 0; 00062 } 00063 00064 #define write16(p, value) \ 00065 do { \ 00066 if (s->big_endian) AV_WB16(p, value); \ 00067 else AV_WL16(p, value); \ 00068 } while(0) 00069 00070 #define write32(p, value) \ 00071 do { \ 00072 if (s->big_endian) AV_WB32(p, value); \ 00073 else AV_WL32(p, value); \ 00074 } while(0) 00075 00076 static void encode_rgb48_10bit(AVCodecContext *avctx, const AVPicture *pic, 00077 uint8_t *dst) 00078 { 00079 DPXContext *s = avctx->priv_data; 00080 const uint8_t *src = pic->data[0]; 00081 int x, y; 00082 00083 for (y = 0; y < avctx->height; y++) { 00084 for (x = 0; x < avctx->width; x++) { 00085 int value; 00086 if ((avctx->pix_fmt & 1)) { 00087 value = ((AV_RB16(src + 6*x + 4) & 0xFFC0) >> 4) 00088 | ((AV_RB16(src + 6*x + 2) & 0xFFC0) << 6) 00089 | ((AV_RB16(src + 6*x + 0) & 0xFFC0) << 16); 00090 } else { 00091 value = ((AV_RL16(src + 6*x + 4) & 0xFFC0) >> 4) 00092 | ((AV_RL16(src + 6*x + 2) & 0xFFC0) << 6) 00093 | ((AV_RL16(src + 6*x + 0) & 0xFFC0) << 16); 00094 } 00095 write32(dst, value); 00096 dst += 4; 00097 } 00098 src += pic->linesize[0]; 00099 } 00100 } 00101 00102 static int encode_frame(AVCodecContext *avctx, unsigned char *buf, 00103 int buf_size, void *data) 00104 { 00105 DPXContext *s = avctx->priv_data; 00106 int size; 00107 00108 #define HEADER_SIZE 1664 /* DPX Generic header */ 00109 if (buf_size < HEADER_SIZE) 00110 return -1; 00111 00112 memset(buf, 0, HEADER_SIZE); 00113 00114 /* File information header */ 00115 write32(buf, MKBETAG('S','D','P','X')); 00116 write32(buf + 4, HEADER_SIZE); 00117 memcpy (buf + 8, "V1.0", 4); 00118 write32(buf + 20, 1); /* new image */ 00119 write32(buf + 24, HEADER_SIZE); 00120 memcpy (buf + 160, LIBAVCODEC_IDENT, FFMIN(sizeof(LIBAVCODEC_IDENT), 100)); 00121 write32(buf + 660, 0xFFFFFFFF); /* unencrypted */ 00122 00123 /* Image information header */ 00124 write16(buf + 768, 0); /* orientation; left to right, top to bottom */ 00125 write16(buf + 770, 1); /* number of elements */ 00126 write32(buf + 772, avctx->width); 00127 write32(buf + 776, avctx->height); 00128 buf[800] = s->descriptor; 00129 buf[801] = 2; /* linear transfer */ 00130 buf[802] = 2; /* linear colorimetric */ 00131 buf[803] = s->bits_per_component; 00132 write16(buf + 804, s->bits_per_component == 10 ? 1 : 0); /* packing method */ 00133 00134 /* Image source information header */ 00135 write32(buf + 1628, avctx->sample_aspect_ratio.num); 00136 write32(buf + 1632, avctx->sample_aspect_ratio.den); 00137 00138 switch (s->bits_per_component) { 00139 case 8: 00140 case 16: 00141 size = avpicture_layout(data, avctx->pix_fmt, 00142 avctx->width, avctx->height, 00143 buf + HEADER_SIZE, buf_size - HEADER_SIZE); 00144 if (size < 0) 00145 return size; 00146 break; 00147 case 10: 00148 size = avctx->height * avctx->width * 4; 00149 if (buf_size < HEADER_SIZE + size) 00150 return -1; 00151 encode_rgb48_10bit(avctx, data, buf + HEADER_SIZE); 00152 break; 00153 default: 00154 av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", s->bits_per_component); 00155 return -1; 00156 } 00157 00158 size += HEADER_SIZE; 00159 00160 write32(buf + 16, size); /* file size */ 00161 return size; 00162 } 00163 00164 AVCodec ff_dpx_encoder = { 00165 .name = "dpx", 00166 .type = AVMEDIA_TYPE_VIDEO, 00167 .id = CODEC_ID_DPX, 00168 .priv_data_size = sizeof(DPXContext), 00169 .init = encode_init, 00170 .encode = encode_frame, 00171 .pix_fmts = (const enum PixelFormat[]){ 00172 PIX_FMT_RGB24, 00173 PIX_FMT_RGBA, 00174 PIX_FMT_RGB48LE, 00175 PIX_FMT_RGB48BE, 00176 PIX_FMT_NONE}, 00177 .long_name = NULL_IF_CONFIG_SMALL("DPX image"), 00178 };