libavcodec/cdxl.c
Go to the documentation of this file.
1 /*
2  * CDXL video decoder
3  * Copyright (c) 2011-2012 Paul B Mahol
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 #define UNCHECKED_BITSTREAM_READER 1
23 
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/imgutils.h"
26 #include "avcodec.h"
27 #include "get_bits.h"
28 #include "internal.h"
29 
30 #define BIT_PLANAR 0x00
31 #define CHUNKY 0x20
32 #define BYTE_PLANAR 0x40
33 #define BIT_LINE 0x80
34 #define BYTE_LINE 0xC0
35 
36 typedef struct {
38  int bpp;
39  int format;
41  const uint8_t *palette;
43  const uint8_t *video;
48 
50 {
51  CDXLVideoContext *c = avctx->priv_data;
52 
53  c->new_video_size = 0;
54  c->avctx = avctx;
55 
56  return 0;
57 }
58 
59 static void import_palette(CDXLVideoContext *c, uint32_t *new_palette)
60 {
61  int i;
62 
63  for (i = 0; i < c->palette_size / 2; i++) {
64  unsigned rgb = AV_RB16(&c->palette[i * 2]);
65  unsigned r = ((rgb >> 8) & 0xF) * 0x11;
66  unsigned g = ((rgb >> 4) & 0xF) * 0x11;
67  unsigned b = (rgb & 0xF) * 0x11;
68  AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b);
69  }
70 }
71 
72 static void bitplanar2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
73 {
74  GetBitContext gb;
75  int x, y, plane;
76 
77  init_get_bits(&gb, c->video, c->video_size * 8);
78  for (plane = 0; plane < c->bpp; plane++) {
79  for (y = 0; y < c->avctx->height; y++) {
80  for (x = 0; x < c->avctx->width; x++)
81  out[linesize * y + x] |= get_bits1(&gb) << plane;
82  skip_bits(&gb, c->padded_bits);
83  }
84  }
85 }
86 
87 static void bitline2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
88 {
89  GetBitContext gb;
90  int x, y, plane;
91 
92  init_get_bits(&gb, c->video, c->video_size * 8);
93  for (y = 0; y < c->avctx->height; y++) {
94  for (plane = 0; plane < c->bpp; plane++) {
95  for (x = 0; x < c->avctx->width; x++)
96  out[linesize * y + x] |= get_bits1(&gb) << plane;
97  skip_bits(&gb, c->padded_bits);
98  }
99  }
100 }
101 
102 static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out)
103 {
104  memset(out, 0, linesize * c->avctx->height);
105 
106  switch (c->format) {
107  case BIT_PLANAR:
108  bitplanar2chunky(c, linesize, out);
109  break;
110  case BIT_LINE:
111  bitline2chunky(c, linesize, out);
112  break;
113  }
114 }
115 
117 {
118  uint32_t *new_palette = (uint32_t *)frame->data[1];
119 
120  memset(frame->data[1], 0, AVPALETTE_SIZE);
121  import_palette(c, new_palette);
122  import_format(c, frame->linesize[0], frame->data[0]);
123 }
124 
126 {
127  AVCodecContext *avctx = c->avctx;
128  uint32_t new_palette[16], r, g, b;
129  uint8_t *ptr, *out, index, op;
130  int x, y;
131 
132  ptr = c->new_video;
133  out = frame->data[0];
134 
135  import_palette(c, new_palette);
136  import_format(c, avctx->width, c->new_video);
137 
138  for (y = 0; y < avctx->height; y++) {
139  r = new_palette[0] & 0xFF0000;
140  g = new_palette[0] & 0xFF00;
141  b = new_palette[0] & 0xFF;
142  for (x = 0; x < avctx->width; x++) {
143  index = *ptr++;
144  op = index >> 4;
145  index &= 15;
146  switch (op) {
147  case 0:
148  r = new_palette[index] & 0xFF0000;
149  g = new_palette[index] & 0xFF00;
150  b = new_palette[index] & 0xFF;
151  break;
152  case 1:
153  b = index * 0x11;
154  break;
155  case 2:
156  r = index * 0x11 << 16;
157  break;
158  case 3:
159  g = index * 0x11 << 8;
160  break;
161  }
162  AV_WL24(out + x * 3, r | g | b);
163  }
164  out += frame->linesize[0];
165  }
166 }
167 
169 {
170  AVCodecContext *avctx = c->avctx;
171  uint32_t new_palette[64], r, g, b;
172  uint8_t *ptr, *out, index, op;
173  int x, y;
174 
175  ptr = c->new_video;
176  out = frame->data[0];
177 
178  import_palette(c, new_palette);
179  import_format(c, avctx->width, c->new_video);
180 
181  for (y = 0; y < avctx->height; y++) {
182  r = new_palette[0] & 0xFF0000;
183  g = new_palette[0] & 0xFF00;
184  b = new_palette[0] & 0xFF;
185  for (x = 0; x < avctx->width; x++) {
186  index = *ptr++;
187  op = index >> 6;
188  index &= 63;
189  switch (op) {
190  case 0:
191  r = new_palette[index] & 0xFF0000;
192  g = new_palette[index] & 0xFF00;
193  b = new_palette[index] & 0xFF;
194  break;
195  case 1:
196  b = (index << 2) | (b & 3);
197  break;
198  case 2:
199  r = (index << 18) | (r & (3 << 16));
200  break;
201  case 3:
202  g = (index << 10) | (g & (3 << 8));
203  break;
204  }
205  AV_WL24(out + x * 3, r | g | b);
206  }
207  out += frame->linesize[0];
208  }
209 }
210 
211 static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
212  int *got_frame, AVPacket *pkt)
213 {
214  CDXLVideoContext *c = avctx->priv_data;
215  AVFrame * const p = data;
216  int ret, w, h, encoding, aligned_width, buf_size = pkt->size;
217  const uint8_t *buf = pkt->data;
218 
219  if (buf_size < 32)
220  return AVERROR_INVALIDDATA;
221  encoding = buf[1] & 7;
222  c->format = buf[1] & 0xE0;
223  w = AV_RB16(&buf[14]);
224  h = AV_RB16(&buf[16]);
225  c->bpp = buf[19];
226  c->palette_size = AV_RB16(&buf[20]);
227  c->palette = buf + 32;
228  c->video = c->palette + c->palette_size;
229  c->video_size = buf_size - c->palette_size - 32;
230 
231  if (c->palette_size > 512)
232  return AVERROR_INVALIDDATA;
233  if (buf_size < c->palette_size + 32)
234  return AVERROR_INVALIDDATA;
235  if (c->bpp < 1)
236  return AVERROR_INVALIDDATA;
237  if (c->format != BIT_PLANAR && c->format != BIT_LINE) {
238  avpriv_request_sample(avctx, "Pixel format 0x%0x", c->format);
239  return AVERROR_PATCHWELCOME;
240  }
241 
242  if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
243  return ret;
244  if (w != avctx->width || h != avctx->height)
245  avcodec_set_dimensions(avctx, w, h);
246 
247  aligned_width = FFALIGN(c->avctx->width, 16);
248  c->padded_bits = aligned_width - c->avctx->width;
249  if (c->video_size < aligned_width * avctx->height * c->bpp / 8)
250  return AVERROR_INVALIDDATA;
251  if (!encoding && c->palette_size && c->bpp <= 8) {
252  avctx->pix_fmt = AV_PIX_FMT_PAL8;
253  } else if (encoding == 1 && (c->bpp == 6 || c->bpp == 8)) {
254  if (c->palette_size != (1 << (c->bpp - 1)))
255  return AVERROR_INVALIDDATA;
256  avctx->pix_fmt = AV_PIX_FMT_BGR24;
257  } else {
258  avpriv_request_sample(avctx, "Encoding %d and bpp %d",
259  encoding, c->bpp);
260  return AVERROR_PATCHWELCOME;
261  }
262 
263  if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
264  return ret;
266 
267  if (encoding) {
270  if (!c->new_video)
271  return AVERROR(ENOMEM);
272  if (c->bpp == 8)
273  cdxl_decode_ham8(c, p);
274  else
275  cdxl_decode_ham6(c, p);
276  } else {
277  cdxl_decode_rgb(c, p);
278  }
279  *got_frame = 1;
280 
281  return buf_size;
282 }
283 
285 {
286  CDXLVideoContext *c = avctx->priv_data;
287 
288  av_free(c->new_video);
289 
290  return 0;
291 }
292 
294  .name = "cdxl",
295  .type = AVMEDIA_TYPE_VIDEO,
296  .id = AV_CODEC_ID_CDXL,
297  .priv_data_size = sizeof(CDXLVideoContext),
301  .capabilities = CODEC_CAP_DR1,
302  .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"),
303 };
#define BIT_LINE
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
misc image utilities
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
void avcodec_set_dimensions(AVCodecContext *s, int width, int height)
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional FF_INPUT_BUFFER_PADDING_SIZE at the end w...
static void cdxl_decode_ham8(CDXLVideoContext *c, AVFrame *frame)
output residual component w
#define FFALIGN(x, a)
Definition: common.h:63
const uint8_t * palette
#define AV_WL24(p, d)
Definition: intreadwrite.h:456
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
uint8_t
#define av_cold
Definition: attributes.h:78
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
#define AVPALETTE_SIZE
Definition: pixfmt.h:33
static AVPacket pkt
Definition: demuxing.c:56
#define b
Definition: input.c:42
AVCodec ff_cdxl_decoder
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
static av_cold int cdxl_decode_end(AVCodecContext *avctx)
uint8_t * data
bitstream reader API header.
static int cdxl_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt)
frame
Definition: stft.m:14
Discrete Time axis x
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define AV_RB16
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
const char * r
Definition: vf_curves.c:94
const char * name
Name of the codec implementation.
external API header
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
static void bitline2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:231
FFT buffer for g
Definition: stft_peak.m:17
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:144
ret
Definition: avfilter.c:821
int width
picture width / height.
static av_cold int cdxl_decode_init(AVCodecContext *avctx)
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:71
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
void * buf
Definition: avisynth_c.h:594
AVCodecContext * avctx
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:273
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:265
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:379
#define BIT_PLANAR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static void bitplanar2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
static void cdxl_decode_rgb(CDXLVideoContext *c, AVFrame *frame)
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
common internal api header.
#define AV_WN32(p, v)
Definition: intreadwrite.h:368
static double c[64]
function y
Definition: D.m:1
static void cdxl_decode_ham6(CDXLVideoContext *c, AVFrame *frame)
const uint8_t * video
static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out)
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
This structure stores compressed data.
static void import_palette(CDXLVideoContext *c, uint32_t *new_palette)