1/* 2 * DPX (.dpx) image encoder 3 * Copyright (c) 2011 Peter Ross <pross@xvid.org> 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/common.h" 23#include "libavutil/intreadwrite.h" 24#include "libavutil/imgutils.h" 25#include "avcodec.h" 26#include "internal.h" 27 28typedef struct DPXContext { 29 int big_endian; 30 int bits_per_component; 31 int descriptor; 32 int planar; 33} DPXContext; 34 35static av_cold int encode_init(AVCodecContext *avctx) 36{ 37 DPXContext *s = avctx->priv_data; 38 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); 39 40 s->big_endian = !!(desc->flags & AV_PIX_FMT_FLAG_BE); 41 s->bits_per_component = desc->comp[0].depth_minus1 + 1; 42 s->descriptor = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? 51 : 50; 43 s->planar = !!(desc->flags & AV_PIX_FMT_FLAG_PLANAR); 44 45 switch (avctx->pix_fmt) { 46 case AV_PIX_FMT_ABGR: 47 s->descriptor = 52; 48 break; 49 case AV_PIX_FMT_GRAY16BE: 50 case AV_PIX_FMT_GRAY16LE: 51 case AV_PIX_FMT_GRAY8: 52 s->descriptor = 6; 53 break; 54 case AV_PIX_FMT_GBRP10BE: 55 case AV_PIX_FMT_GBRP10LE: 56 case AV_PIX_FMT_GBRP12BE: 57 case AV_PIX_FMT_GBRP12LE: 58 case AV_PIX_FMT_RGB24: 59 case AV_PIX_FMT_RGBA64BE: 60 case AV_PIX_FMT_RGBA64LE: 61 case AV_PIX_FMT_RGBA: 62 break; 63 case AV_PIX_FMT_RGB48LE: 64 case AV_PIX_FMT_RGB48BE: 65 if (avctx->bits_per_raw_sample) 66 s->bits_per_component = avctx->bits_per_raw_sample; 67 break; 68 default: 69 av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); 70 return -1; 71 } 72 73 return 0; 74} 75 76#define write16(p, value) \ 77do { \ 78 if (s->big_endian) AV_WB16(p, value); \ 79 else AV_WL16(p, value); \ 80} while(0) 81 82#define write32(p, value) \ 83do { \ 84 if (s->big_endian) AV_WB32(p, value); \ 85 else AV_WL32(p, value); \ 86} while(0) 87 88static void encode_rgb48_10bit(AVCodecContext *avctx, const AVPicture *pic, uint8_t *dst) 89{ 90 DPXContext *s = avctx->priv_data; 91 const uint8_t *src = pic->data[0]; 92 int x, y; 93 94 for (y = 0; y < avctx->height; y++) { 95 for (x = 0; x < avctx->width; x++) { 96 int value; 97 if (s->big_endian) { 98 value = ((AV_RB16(src + 6*x + 4) & 0xFFC0U) >> 4) 99 | ((AV_RB16(src + 6*x + 2) & 0xFFC0U) << 6) 100 | ((AV_RB16(src + 6*x + 0) & 0xFFC0U) << 16); 101 } else { 102 value = ((AV_RL16(src + 6*x + 4) & 0xFFC0U) >> 4) 103 | ((AV_RL16(src + 6*x + 2) & 0xFFC0U) << 6) 104 | ((AV_RL16(src + 6*x + 0) & 0xFFC0U) << 16); 105 } 106 write32(dst, value); 107 dst += 4; 108 } 109 src += pic->linesize[0]; 110 } 111} 112 113static void encode_gbrp10(AVCodecContext *avctx, const AVPicture *pic, uint8_t *dst) 114{ 115 DPXContext *s = avctx->priv_data; 116 const uint8_t *src[3] = {pic->data[0], pic->data[1], pic->data[2]}; 117 int x, y, i; 118 119 for (y = 0; y < avctx->height; y++) { 120 for (x = 0; x < avctx->width; x++) { 121 int value; 122 if (s->big_endian) { 123 value = (AV_RB16(src[0] + 2*x) << 12) 124 | (AV_RB16(src[1] + 2*x) << 2) 125 | ((unsigned)AV_RB16(src[2] + 2*x) << 22); 126 } else { 127 value = (AV_RL16(src[0] + 2*x) << 12) 128 | (AV_RL16(src[1] + 2*x) << 2) 129 | ((unsigned)AV_RL16(src[2] + 2*x) << 22); 130 } 131 write32(dst, value); 132 dst += 4; 133 } 134 for (i = 0; i < 3; i++) 135 src[i] += pic->linesize[i]; 136 } 137} 138 139static void encode_gbrp12(AVCodecContext *avctx, const AVPicture *pic, uint16_t *dst) 140{ 141 DPXContext *s = avctx->priv_data; 142 const uint16_t *src[3] = {(uint16_t*)pic->data[0], 143 (uint16_t*)pic->data[1], 144 (uint16_t*)pic->data[2]}; 145 int x, y, i; 146 for (y = 0; y < avctx->height; y++) { 147 for (x = 0; x < avctx->width; x++) { 148 uint16_t value[3]; 149 if (s->big_endian) { 150 value[1] = AV_RB16(src[0] + x) << 4; 151 value[2] = AV_RB16(src[1] + x) << 4; 152 value[0] = AV_RB16(src[2] + x) << 4; 153 } else { 154 value[1] = AV_RL16(src[0] + x) << 4; 155 value[2] = AV_RL16(src[1] + x) << 4; 156 value[0] = AV_RL16(src[2] + x) << 4; 157 } 158 for (i = 0; i < 3; i++) 159 write16(dst++, value[i]); 160 } 161 for (i = 0; i < 3; i++) 162 src[i] += pic->linesize[i]/2; 163 } 164} 165 166static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, 167 const AVFrame *frame, int *got_packet) 168{ 169 DPXContext *s = avctx->priv_data; 170 int size, ret; 171 uint8_t *buf; 172 173#define HEADER_SIZE 1664 /* DPX Generic header */ 174 if (s->bits_per_component == 10) 175 size = avctx->height * avctx->width * 4; 176 else 177 size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); 178 if ((ret = ff_alloc_packet2(avctx, pkt, size + HEADER_SIZE)) < 0) 179 return ret; 180 buf = pkt->data; 181 182 memset(buf, 0, HEADER_SIZE); 183 184 /* File information header */ 185 write32(buf, MKBETAG('S','D','P','X')); 186 write32(buf + 4, HEADER_SIZE); 187 memcpy (buf + 8, "V1.0", 4); 188 write32(buf + 20, 1); /* new image */ 189 write32(buf + 24, HEADER_SIZE); 190 if (!(avctx->flags & CODEC_FLAG_BITEXACT)) 191 memcpy (buf + 160, LIBAVCODEC_IDENT, FFMIN(sizeof(LIBAVCODEC_IDENT), 100)); 192 write32(buf + 660, 0xFFFFFFFF); /* unencrypted */ 193 194 /* Image information header */ 195 write16(buf + 768, 0); /* orientation; left to right, top to bottom */ 196 write16(buf + 770, 1); /* number of elements */ 197 write32(buf + 772, avctx->width); 198 write32(buf + 776, avctx->height); 199 buf[800] = s->descriptor; 200 buf[801] = 2; /* linear transfer */ 201 buf[802] = 2; /* linear colorimetric */ 202 buf[803] = s->bits_per_component; 203 write16(buf + 804, (s->bits_per_component == 10 || s->bits_per_component == 12) ? 204 1 : 0); /* packing method */ 205 write32(buf + 808, HEADER_SIZE); /* data offset */ 206 207 /* Image source information header */ 208 write32(buf + 1628, avctx->sample_aspect_ratio.num); 209 write32(buf + 1632, avctx->sample_aspect_ratio.den); 210 211 switch(s->bits_per_component) { 212 case 8: 213 case 16: 214 size = avpicture_layout((const AVPicture*)frame, avctx->pix_fmt, 215 avctx->width, avctx->height, 216 buf + HEADER_SIZE, pkt->size - HEADER_SIZE); 217 if (size < 0) 218 return size; 219 break; 220 case 10: 221 if (s->planar) 222 encode_gbrp10(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); 223 else 224 encode_rgb48_10bit(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); 225 break; 226 case 12: 227 encode_gbrp12(avctx, (const AVPicture*)frame, (uint16_t*)(buf + HEADER_SIZE)); 228 break; 229 default: 230 av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", s->bits_per_component); 231 return -1; 232 } 233 234 size += HEADER_SIZE; 235 236 write32(buf + 16, size); /* file size */ 237 238 pkt->flags |= AV_PKT_FLAG_KEY; 239 *got_packet = 1; 240 241 return 0; 242} 243 244AVCodec ff_dpx_encoder = { 245 .name = "dpx", 246 .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), 247 .type = AVMEDIA_TYPE_VIDEO, 248 .id = AV_CODEC_ID_DPX, 249 .priv_data_size = sizeof(DPXContext), 250 .init = encode_init, 251 .encode2 = encode_frame, 252 .pix_fmts = (const enum AVPixelFormat[]){ 253 AV_PIX_FMT_GRAY8, 254 AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_ABGR, 255 AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, 256 AV_PIX_FMT_RGB48LE, AV_PIX_FMT_RGB48BE, 257 AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_RGBA64BE, 258 AV_PIX_FMT_GBRP10LE, AV_PIX_FMT_GBRP10BE, 259 AV_PIX_FMT_GBRP12LE, AV_PIX_FMT_GBRP12BE, 260 AV_PIX_FMT_NONE}, 261}; 262