annotate ffmpeg/libavcodec/cdxl.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * CDXL video decoder
yading@10 3 * Copyright (c) 2011-2012 Paul B Mahol
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 #define UNCHECKED_BITSTREAM_READER 1
yading@10 23
yading@10 24 #include "libavutil/intreadwrite.h"
yading@10 25 #include "libavutil/imgutils.h"
yading@10 26 #include "avcodec.h"
yading@10 27 #include "get_bits.h"
yading@10 28 #include "internal.h"
yading@10 29
yading@10 30 #define BIT_PLANAR 0x00
yading@10 31 #define CHUNKY 0x20
yading@10 32 #define BYTE_PLANAR 0x40
yading@10 33 #define BIT_LINE 0x80
yading@10 34 #define BYTE_LINE 0xC0
yading@10 35
yading@10 36 typedef struct {
yading@10 37 AVCodecContext *avctx;
yading@10 38 int bpp;
yading@10 39 int format;
yading@10 40 int padded_bits;
yading@10 41 const uint8_t *palette;
yading@10 42 int palette_size;
yading@10 43 const uint8_t *video;
yading@10 44 int video_size;
yading@10 45 uint8_t *new_video;
yading@10 46 int new_video_size;
yading@10 47 } CDXLVideoContext;
yading@10 48
yading@10 49 static av_cold int cdxl_decode_init(AVCodecContext *avctx)
yading@10 50 {
yading@10 51 CDXLVideoContext *c = avctx->priv_data;
yading@10 52
yading@10 53 c->new_video_size = 0;
yading@10 54 c->avctx = avctx;
yading@10 55
yading@10 56 return 0;
yading@10 57 }
yading@10 58
yading@10 59 static void import_palette(CDXLVideoContext *c, uint32_t *new_palette)
yading@10 60 {
yading@10 61 int i;
yading@10 62
yading@10 63 for (i = 0; i < c->palette_size / 2; i++) {
yading@10 64 unsigned rgb = AV_RB16(&c->palette[i * 2]);
yading@10 65 unsigned r = ((rgb >> 8) & 0xF) * 0x11;
yading@10 66 unsigned g = ((rgb >> 4) & 0xF) * 0x11;
yading@10 67 unsigned b = (rgb & 0xF) * 0x11;
yading@10 68 AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b);
yading@10 69 }
yading@10 70 }
yading@10 71
yading@10 72 static void bitplanar2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
yading@10 73 {
yading@10 74 GetBitContext gb;
yading@10 75 int x, y, plane;
yading@10 76
yading@10 77 init_get_bits(&gb, c->video, c->video_size * 8);
yading@10 78 for (plane = 0; plane < c->bpp; plane++) {
yading@10 79 for (y = 0; y < c->avctx->height; y++) {
yading@10 80 for (x = 0; x < c->avctx->width; x++)
yading@10 81 out[linesize * y + x] |= get_bits1(&gb) << plane;
yading@10 82 skip_bits(&gb, c->padded_bits);
yading@10 83 }
yading@10 84 }
yading@10 85 }
yading@10 86
yading@10 87 static void bitline2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
yading@10 88 {
yading@10 89 GetBitContext gb;
yading@10 90 int x, y, plane;
yading@10 91
yading@10 92 init_get_bits(&gb, c->video, c->video_size * 8);
yading@10 93 for (y = 0; y < c->avctx->height; y++) {
yading@10 94 for (plane = 0; plane < c->bpp; plane++) {
yading@10 95 for (x = 0; x < c->avctx->width; x++)
yading@10 96 out[linesize * y + x] |= get_bits1(&gb) << plane;
yading@10 97 skip_bits(&gb, c->padded_bits);
yading@10 98 }
yading@10 99 }
yading@10 100 }
yading@10 101
yading@10 102 static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out)
yading@10 103 {
yading@10 104 memset(out, 0, linesize * c->avctx->height);
yading@10 105
yading@10 106 switch (c->format) {
yading@10 107 case BIT_PLANAR:
yading@10 108 bitplanar2chunky(c, linesize, out);
yading@10 109 break;
yading@10 110 case BIT_LINE:
yading@10 111 bitline2chunky(c, linesize, out);
yading@10 112 break;
yading@10 113 }
yading@10 114 }
yading@10 115
yading@10 116 static void cdxl_decode_rgb(CDXLVideoContext *c, AVFrame *frame)
yading@10 117 {
yading@10 118 uint32_t *new_palette = (uint32_t *)frame->data[1];
yading@10 119
yading@10 120 memset(frame->data[1], 0, AVPALETTE_SIZE);
yading@10 121 import_palette(c, new_palette);
yading@10 122 import_format(c, frame->linesize[0], frame->data[0]);
yading@10 123 }
yading@10 124
yading@10 125 static void cdxl_decode_ham6(CDXLVideoContext *c, AVFrame *frame)
yading@10 126 {
yading@10 127 AVCodecContext *avctx = c->avctx;
yading@10 128 uint32_t new_palette[16], r, g, b;
yading@10 129 uint8_t *ptr, *out, index, op;
yading@10 130 int x, y;
yading@10 131
yading@10 132 ptr = c->new_video;
yading@10 133 out = frame->data[0];
yading@10 134
yading@10 135 import_palette(c, new_palette);
yading@10 136 import_format(c, avctx->width, c->new_video);
yading@10 137
yading@10 138 for (y = 0; y < avctx->height; y++) {
yading@10 139 r = new_palette[0] & 0xFF0000;
yading@10 140 g = new_palette[0] & 0xFF00;
yading@10 141 b = new_palette[0] & 0xFF;
yading@10 142 for (x = 0; x < avctx->width; x++) {
yading@10 143 index = *ptr++;
yading@10 144 op = index >> 4;
yading@10 145 index &= 15;
yading@10 146 switch (op) {
yading@10 147 case 0:
yading@10 148 r = new_palette[index] & 0xFF0000;
yading@10 149 g = new_palette[index] & 0xFF00;
yading@10 150 b = new_palette[index] & 0xFF;
yading@10 151 break;
yading@10 152 case 1:
yading@10 153 b = index * 0x11;
yading@10 154 break;
yading@10 155 case 2:
yading@10 156 r = index * 0x11 << 16;
yading@10 157 break;
yading@10 158 case 3:
yading@10 159 g = index * 0x11 << 8;
yading@10 160 break;
yading@10 161 }
yading@10 162 AV_WL24(out + x * 3, r | g | b);
yading@10 163 }
yading@10 164 out += frame->linesize[0];
yading@10 165 }
yading@10 166 }
yading@10 167
yading@10 168 static void cdxl_decode_ham8(CDXLVideoContext *c, AVFrame *frame)
yading@10 169 {
yading@10 170 AVCodecContext *avctx = c->avctx;
yading@10 171 uint32_t new_palette[64], r, g, b;
yading@10 172 uint8_t *ptr, *out, index, op;
yading@10 173 int x, y;
yading@10 174
yading@10 175 ptr = c->new_video;
yading@10 176 out = frame->data[0];
yading@10 177
yading@10 178 import_palette(c, new_palette);
yading@10 179 import_format(c, avctx->width, c->new_video);
yading@10 180
yading@10 181 for (y = 0; y < avctx->height; y++) {
yading@10 182 r = new_palette[0] & 0xFF0000;
yading@10 183 g = new_palette[0] & 0xFF00;
yading@10 184 b = new_palette[0] & 0xFF;
yading@10 185 for (x = 0; x < avctx->width; x++) {
yading@10 186 index = *ptr++;
yading@10 187 op = index >> 6;
yading@10 188 index &= 63;
yading@10 189 switch (op) {
yading@10 190 case 0:
yading@10 191 r = new_palette[index] & 0xFF0000;
yading@10 192 g = new_palette[index] & 0xFF00;
yading@10 193 b = new_palette[index] & 0xFF;
yading@10 194 break;
yading@10 195 case 1:
yading@10 196 b = (index << 2) | (b & 3);
yading@10 197 break;
yading@10 198 case 2:
yading@10 199 r = (index << 18) | (r & (3 << 16));
yading@10 200 break;
yading@10 201 case 3:
yading@10 202 g = (index << 10) | (g & (3 << 8));
yading@10 203 break;
yading@10 204 }
yading@10 205 AV_WL24(out + x * 3, r | g | b);
yading@10 206 }
yading@10 207 out += frame->linesize[0];
yading@10 208 }
yading@10 209 }
yading@10 210
yading@10 211 static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
yading@10 212 int *got_frame, AVPacket *pkt)
yading@10 213 {
yading@10 214 CDXLVideoContext *c = avctx->priv_data;
yading@10 215 AVFrame * const p = data;
yading@10 216 int ret, w, h, encoding, aligned_width, buf_size = pkt->size;
yading@10 217 const uint8_t *buf = pkt->data;
yading@10 218
yading@10 219 if (buf_size < 32)
yading@10 220 return AVERROR_INVALIDDATA;
yading@10 221 encoding = buf[1] & 7;
yading@10 222 c->format = buf[1] & 0xE0;
yading@10 223 w = AV_RB16(&buf[14]);
yading@10 224 h = AV_RB16(&buf[16]);
yading@10 225 c->bpp = buf[19];
yading@10 226 c->palette_size = AV_RB16(&buf[20]);
yading@10 227 c->palette = buf + 32;
yading@10 228 c->video = c->palette + c->palette_size;
yading@10 229 c->video_size = buf_size - c->palette_size - 32;
yading@10 230
yading@10 231 if (c->palette_size > 512)
yading@10 232 return AVERROR_INVALIDDATA;
yading@10 233 if (buf_size < c->palette_size + 32)
yading@10 234 return AVERROR_INVALIDDATA;
yading@10 235 if (c->bpp < 1)
yading@10 236 return AVERROR_INVALIDDATA;
yading@10 237 if (c->format != BIT_PLANAR && c->format != BIT_LINE) {
yading@10 238 avpriv_request_sample(avctx, "Pixel format 0x%0x", c->format);
yading@10 239 return AVERROR_PATCHWELCOME;
yading@10 240 }
yading@10 241
yading@10 242 if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
yading@10 243 return ret;
yading@10 244 if (w != avctx->width || h != avctx->height)
yading@10 245 avcodec_set_dimensions(avctx, w, h);
yading@10 246
yading@10 247 aligned_width = FFALIGN(c->avctx->width, 16);
yading@10 248 c->padded_bits = aligned_width - c->avctx->width;
yading@10 249 if (c->video_size < aligned_width * avctx->height * c->bpp / 8)
yading@10 250 return AVERROR_INVALIDDATA;
yading@10 251 if (!encoding && c->palette_size && c->bpp <= 8) {
yading@10 252 avctx->pix_fmt = AV_PIX_FMT_PAL8;
yading@10 253 } else if (encoding == 1 && (c->bpp == 6 || c->bpp == 8)) {
yading@10 254 if (c->palette_size != (1 << (c->bpp - 1)))
yading@10 255 return AVERROR_INVALIDDATA;
yading@10 256 avctx->pix_fmt = AV_PIX_FMT_BGR24;
yading@10 257 } else {
yading@10 258 avpriv_request_sample(avctx, "Encoding %d and bpp %d",
yading@10 259 encoding, c->bpp);
yading@10 260 return AVERROR_PATCHWELCOME;
yading@10 261 }
yading@10 262
yading@10 263 if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
yading@10 264 return ret;
yading@10 265 p->pict_type = AV_PICTURE_TYPE_I;
yading@10 266
yading@10 267 if (encoding) {
yading@10 268 av_fast_padded_malloc(&c->new_video, &c->new_video_size,
yading@10 269 h * w + FF_INPUT_BUFFER_PADDING_SIZE);
yading@10 270 if (!c->new_video)
yading@10 271 return AVERROR(ENOMEM);
yading@10 272 if (c->bpp == 8)
yading@10 273 cdxl_decode_ham8(c, p);
yading@10 274 else
yading@10 275 cdxl_decode_ham6(c, p);
yading@10 276 } else {
yading@10 277 cdxl_decode_rgb(c, p);
yading@10 278 }
yading@10 279 *got_frame = 1;
yading@10 280
yading@10 281 return buf_size;
yading@10 282 }
yading@10 283
yading@10 284 static av_cold int cdxl_decode_end(AVCodecContext *avctx)
yading@10 285 {
yading@10 286 CDXLVideoContext *c = avctx->priv_data;
yading@10 287
yading@10 288 av_free(c->new_video);
yading@10 289
yading@10 290 return 0;
yading@10 291 }
yading@10 292
yading@10 293 AVCodec ff_cdxl_decoder = {
yading@10 294 .name = "cdxl",
yading@10 295 .type = AVMEDIA_TYPE_VIDEO,
yading@10 296 .id = AV_CODEC_ID_CDXL,
yading@10 297 .priv_data_size = sizeof(CDXLVideoContext),
yading@10 298 .init = cdxl_decode_init,
yading@10 299 .close = cdxl_decode_end,
yading@10 300 .decode = cdxl_decode_frame,
yading@10 301 .capabilities = CODEC_CAP_DR1,
yading@10 302 .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"),
yading@10 303 };