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