FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dpxenc.c
Go to the documentation of this file.
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 
28 typedef struct DPXContext {
32  int planar;
33 } DPXContext;
34 
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;
51  case AV_PIX_FMT_GRAY8:
52  s->descriptor = 6;
53  break;
58  case AV_PIX_FMT_RGB24:
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)
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) \
77 do { \
78  if (s->big_endian) AV_WB16(p, value); \
79  else AV_WL16(p, value); \
80 } while(0)
81 
82 #define write32(p, value) \
83 do { \
84  if (s->big_endian) AV_WB32(p, value); \
85  else AV_WL32(p, value); \
86 } while(0)
87 
88 static 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 
113 static 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 
139 static 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 
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 
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[]){
261 };