1/* 2 * Kodak PhotoCD (a.k.a. ImagePac) image decoder 3 * 4 * Copyright (c) 1996-2002 Gerd Knorr 5 * Copyright (c) 2010 Kenneth Vermeirsch 6 * Copyright (c) 2020 Paul B Mahol 7 * 8 * This file is part of FFmpeg. 9 * 10 * FFmpeg is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * FFmpeg is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with FFmpeg; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25/** 26 * @file 27 * Kodak PhotoCD (a.k.a. ImagePac) image decoder 28 * 29 * Supports resolutions up to 3072x2048. 30 */ 31 32#define CACHED_BITSTREAM_READER !ARCH_X86_32 33 34#include "libavutil/intreadwrite.h" 35#include "libavutil/opt.h" 36#include "avcodec.h" 37#include "bytestream.h" 38#include "codec_internal.h" 39#include "get_bits.h" 40#include "internal.h" 41#include "thread.h" 42 43typedef struct PhotoCDContext { 44 AVClass *class; 45 int lowres; 46 47 GetByteContext gb; 48 int thumbnails; //* number of thumbnails; 0 for normal image */ 49 int resolution; 50 int orientation; 51 52 int streampos; 53 54 uint8_t bits[256]; 55 uint16_t codes[256]; 56 uint8_t syms[256]; 57 58 VLC vlc[3]; 59} PhotoCDContext; 60 61typedef struct ImageInfo { 62 uint32_t start; 63 uint16_t width, height; 64} ImageInfo; 65 66static const ImageInfo img_info[6] = { 67 {8192, 192, 128}, 68 {47104, 384, 256}, 69 {196608, 768, 512}, 70 {0, 1536, 1024}, 71 {0, 3072, 2048}, 72 {0, 6144, 4096}, 73}; 74 75static av_noinline void interp_lowres(PhotoCDContext *s, AVFrame *picture, 76 int width, int height) 77{ 78 GetByteContext *gb = &s->gb; 79 int start = s->streampos + img_info[2].start; 80 uint8_t *ptr, *ptr1, *ptr2; 81 uint8_t *dst; 82 int fill; 83 84 ptr = picture->data[0]; 85 ptr1 = picture->data[1]; 86 ptr2 = picture->data[2]; 87 88 bytestream2_seek(gb, start, SEEK_SET); 89 90 for (int y = 0; y < height; y += 2) { 91 dst = ptr; 92 for (int x = 0; x < width - 1; x++) { 93 fill = bytestream2_get_byte(gb); 94 *(dst++) = fill; 95 *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; 96 } 97 fill = bytestream2_get_byte(gb); 98 *(dst++) = fill; 99 *(dst++) = fill; 100 101 ptr += picture->linesize[0] << 1; 102 103 dst = ptr; 104 for (int x = 0; x < width - 1; x++) { 105 fill = bytestream2_get_byte(gb); 106 *(dst++) = fill; 107 *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; 108 } 109 fill = bytestream2_get_byte(gb); 110 *(dst++) = fill; 111 *(dst++) = fill; 112 113 ptr += picture->linesize[0] << 1; 114 115 dst = ptr1; 116 for (int x = 0; x < (width >> 1) - 1; x++) { 117 fill = bytestream2_get_byte(gb); 118 *(dst++) = fill; 119 *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; 120 } 121 fill = bytestream2_get_byte(gb); 122 *(dst++) = fill; 123 *(dst++) = fill; 124 125 ptr1 += picture->linesize[1] << 1; 126 127 dst = ptr2; 128 for (int x = 0; x < (width >> 1) - 1; x++) { 129 fill = bytestream2_get_byte(gb); 130 *(dst++) = fill; 131 *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; 132 } 133 fill = bytestream2_get_byte(gb); 134 *(dst++) = fill; 135 *(dst++) = fill; 136 137 ptr2 += picture->linesize[2] << 1; 138 } 139 140 s->streampos += bytestream2_tell(gb) - start; 141} 142 143static av_noinline void interp_lines(uint8_t *ptr, int linesize, 144 int width, int height) 145{ 146 const uint8_t *src1; 147 uint8_t *dst; 148 int x; 149 150 for (int y = 0; y < height - 2; y += 2) { 151 const uint8_t *src1 = ptr; 152 uint8_t *dst = ptr + linesize; 153 const uint8_t *src2 = dst + linesize; 154 for (x = 0; x < width - 2; x += 2) { 155 dst[x] = (src1[x] + src2[x] + 1) >> 1; 156 dst[x + 1] = (src1[x] + src2[x] + src1[x + 2] + src2[x + 2] + 2) >> 2; 157 } 158 dst[x] = dst[x + 1] = (src1[x] + src2[x] + 1) >> 1; 159 160 ptr += linesize << 1; 161 } 162 163 src1 = ptr; 164 dst = ptr + linesize; 165 for (x = 0; x < width - 2; x += 2) { 166 dst[x] = src1[x]; 167 dst[x + 1] = (src1[x] + src1[x + 2] + 1) >> 1; 168 } 169 dst[x] = dst[x + 1] = src1[x]; 170} 171 172static av_noinline void interp_pixels(uint8_t *ptr, int linesize, 173 int width, int height) 174{ 175 for (int y = height - 2; y >= 0; y -= 2) { 176 const uint8_t *src = ptr + (y >> 1) * linesize; 177 uint8_t *dst = ptr + y * linesize; 178 179 dst[width - 2] = dst[width - 1] = src[(width >> 1) - 1]; 180 for (int x = width - 4; x >= 0; x -= 2) { 181 dst[x] = src[x >> 1]; 182 dst[x + 1] = (src[x >> 1] + src[(x >> 1) + 1] + 1) >> 1; 183 } 184 } 185} 186 187static av_noinline int read_hufftable(AVCodecContext *avctx, VLC *vlc) 188{ 189 PhotoCDContext *s = avctx->priv_data; 190 GetByteContext *gb = &s->gb; 191 int start = s->streampos; 192 int count, ret; 193 194 bytestream2_seek(gb, start, SEEK_SET); 195 196 count = bytestream2_get_byte(gb) + 1; 197 if (bytestream2_get_bytes_left(gb) < count * 4) 198 return AVERROR_INVALIDDATA; 199 200 for (int j = 0; j < count; j++) { 201 const int bit = bytestream2_get_byteu(gb) + 1; 202 const int code = bytestream2_get_be16u(gb); 203 const int sym = bytestream2_get_byteu(gb); 204 205 if (bit > 16) 206 return AVERROR_INVALIDDATA; 207 208 s->bits[j] = bit; 209 s->codes[j] = code >> (16 - bit); 210 s->syms[j] = sym; 211 } 212 213 ff_free_vlc(vlc); 214 ret = ff_init_vlc_sparse(vlc, 12, count, 215 s->bits, sizeof(*s->bits), sizeof(*s->bits), 216 s->codes, sizeof(*s->codes), sizeof(*s->codes), 217 s->syms, sizeof(*s->syms), sizeof(*s->syms), 0); 218 219 s->streampos = bytestream2_tell(gb); 220 221 return ret; 222} 223 224static av_noinline int decode_huff(AVCodecContext *avctx, AVFrame *frame, 225 int target_res, int curr_res) 226{ 227 PhotoCDContext *s = avctx->priv_data; 228 GetBitContext g; 229 GetByteContext *gb = &s->gb; 230 int ret, y = 0, type, height; 231 int start = s->streampos; 232 unsigned shiftreg; 233 const int scaling = target_res - curr_res; 234 const uint8_t type2idx[] = { 0, 0xff, 1, 2 }; 235 236 bytestream2_seek(gb, start, SEEK_SET); 237 ret = init_get_bits8(&g, gb->buffer, bytestream2_get_bytes_left(gb)); 238 if (ret < 0) 239 return ret; 240 241 height = img_info[curr_res].height; 242 243 while (y < height) { 244 uint8_t *data; 245 int x2, idx; 246 247 for (; get_bits_left(&g) > 0;) { 248 if (show_bits(&g, 12) == 0xfff) 249 break; 250 skip_bits(&g, 8); 251 } 252 253 shiftreg = show_bits(&g, 24); 254 while (shiftreg != 0xfffffe) { 255 if (get_bits_left(&g) <= 0) 256 return AVERROR_INVALIDDATA; 257 skip_bits(&g, 1); 258 shiftreg = show_bits(&g, 24); 259 } 260 skip_bits(&g, 24); 261 y = show_bits(&g, 15) & 0x1fff; 262 if (y >= height) 263 break; 264 type = get_bits(&g, 2); 265 skip_bits(&g, 14); 266 267 if (type == 1) 268 return AVERROR_INVALIDDATA; 269 idx = type2idx[type]; 270 271 data = frame->data[idx] + (y >> !!idx) * frame->linesize[idx]; 272 273 x2 = avctx->width >> (scaling + !!idx); 274 for (int x = 0; x < x2; x++) { 275 int m; 276 277 if (get_bits_left(&g) <= 0) 278 return AVERROR_INVALIDDATA; 279 m = get_vlc2(&g, s->vlc[idx].table, s->vlc[idx].bits, 2); 280 if (m < 0) 281 return AVERROR_INVALIDDATA; 282 m = sign_extend(m, 8); 283 data[x] = av_clip_uint8(data[x] + m); 284 } 285 } 286 287 s->streampos += (get_bits_count(&g) + 7) >> 3; 288 s->streampos = (s->streampos + 0x6000 + 2047) & ~0x7ff; 289 290 return 0; 291} 292 293static int photocd_decode_frame(AVCodecContext *avctx, AVFrame *p, 294 int *got_frame, AVPacket *avpkt) 295{ 296 PhotoCDContext *s = avctx->priv_data; 297 const uint8_t *buf = avpkt->data; 298 GetByteContext *gb = &s->gb; 299 uint8_t *ptr, *ptr1, *ptr2; 300 int ret; 301 302 if (avpkt->size < img_info[0].start) 303 return AVERROR_INVALIDDATA; 304 305 if (!memcmp("PCD_OPA", buf, 7)) { 306 s->thumbnails = AV_RL16(buf + 10); 307 av_log(avctx, AV_LOG_WARNING, "this is a thumbnails file, " 308 "reading first thumbnail only\n"); 309 } else if (avpkt->size < 786432) { 310 return AVERROR_INVALIDDATA; 311 } else if (memcmp("PCD_IPI", buf + 0x800, 7)) { 312 return AVERROR_INVALIDDATA; 313 } 314 315 s->orientation = s->thumbnails ? buf[12] & 3 : buf[0x48] & 3; 316 317 if (s->thumbnails) 318 s->resolution = 0; 319 else if (avpkt->size <= 788480) 320 s->resolution = 2; 321 else 322 s->resolution = av_clip(4 - s->lowres, 0, 4); 323 324 ret = ff_set_dimensions(avctx, img_info[s->resolution].width, img_info[s->resolution].height); 325 if (ret < 0) 326 return ret; 327 328 if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) 329 return ret; 330 331 p->pict_type = AV_PICTURE_TYPE_I; 332 p->key_frame = 1; 333 334 bytestream2_init(gb, avpkt->data, avpkt->size); 335 336 if (s->resolution < 3) { 337 ptr = p->data[0]; 338 ptr1 = p->data[1]; 339 ptr2 = p->data[2]; 340 341 if (s->thumbnails) 342 bytestream2_seek(gb, 10240, SEEK_SET); 343 else 344 bytestream2_seek(gb, img_info[s->resolution].start, SEEK_SET); 345 346 for (int y = 0; y < avctx->height; y += 2) { 347 bytestream2_get_buffer(gb, ptr, avctx->width); 348 ptr += p->linesize[0]; 349 350 bytestream2_get_buffer(gb, ptr, avctx->width); 351 ptr += p->linesize[0]; 352 353 bytestream2_get_buffer(gb, ptr1, avctx->width >> 1); 354 ptr1 += p->linesize[1]; 355 356 bytestream2_get_buffer(gb, ptr2, avctx->width >> 1); 357 ptr2 += p->linesize[2]; 358 } 359 } else { 360 s->streampos = 0; 361 ptr = p->data[0]; 362 ptr1 = p->data[1]; 363 ptr2 = p->data[2]; 364 365 interp_lowres(s, p, img_info[2].width, img_info[2].height); 366 367 interp_lines(ptr1, p->linesize[1], img_info[2].width, img_info[2].height); 368 interp_lines(ptr2, p->linesize[2], img_info[2].width, img_info[2].height); 369 370 if (s->resolution == 4) { 371 interp_pixels(ptr1, p->linesize[1], img_info[3].width, img_info[3].height); 372 interp_lines (ptr1, p->linesize[1], img_info[3].width, img_info[3].height); 373 interp_pixels(ptr2, p->linesize[2], img_info[3].width, img_info[3].height); 374 interp_lines (ptr2, p->linesize[2], img_info[3].width, img_info[3].height); 375 } 376 377 interp_lines(ptr, p->linesize[0], img_info[3].width, img_info[3].height); 378 379 s->streampos = 0xc2000; 380 for (int n = 0; n < 3; n++) { 381 if ((ret = read_hufftable(avctx, &s->vlc[n])) < 0) 382 return ret; 383 } 384 s->streampos = (s->streampos + 2047) & ~0x3ff; 385 if (decode_huff(avctx, p, s->resolution, 3) < 0) 386 return AVERROR_INVALIDDATA; 387 388 if (s->resolution == 4) { 389 interp_pixels(ptr, p->linesize[0], img_info[4].width, img_info[4].height); 390 interp_lines (ptr, p->linesize[0], img_info[4].width, img_info[4].height); 391 392 for (int n = 0; n < 3; n++) { 393 if ((ret = read_hufftable(avctx, &s->vlc[n])) < 0) 394 return ret; 395 } 396 s->streampos = (s->streampos + 2047) & ~0x3ff; 397 if (decode_huff(avctx, p, 4, 4) < 0) 398 return AVERROR_INVALIDDATA; 399 } 400 } 401 402 { 403 ptr1 = p->data[1]; 404 ptr2 = p->data[2]; 405 406 for (int y = 0; y < avctx->height >> 1; y++) { 407 for (int x = 0; x < avctx->width >> 1; x++) { 408 ptr1[x] = av_clip_uint8(ptr1[x] - 28); 409 ptr2[x] = av_clip_uint8(ptr2[x] - 9); 410 } 411 412 ptr1 += p->linesize[1]; 413 ptr2 += p->linesize[2]; 414 } 415 } 416 417 *got_frame = 1; 418 419 return 0; 420} 421 422static av_cold int photocd_decode_init(AVCodecContext *avctx) 423{ 424 avctx->pix_fmt = AV_PIX_FMT_YUV420P; 425 avctx->colorspace = AVCOL_SPC_BT709; 426 avctx->color_primaries = AVCOL_PRI_BT709; 427 avctx->color_trc = AVCOL_TRC_IEC61966_2_1; 428 avctx->color_range = AVCOL_RANGE_JPEG; 429 430 return 0; 431} 432 433static av_cold int photocd_decode_close(AVCodecContext *avctx) 434{ 435 PhotoCDContext *s = avctx->priv_data; 436 437 for (int i = 0; i < 3; i++) 438 ff_free_vlc(&s->vlc[i]); 439 440 return 0; 441} 442 443#define OFFSET(x) offsetof(PhotoCDContext, x) 444#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM 445 446static const AVOption options[] = { 447 { "lowres", "Lower the decoding resolution by a power of two", 448 OFFSET(lowres), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, VD }, 449 { NULL }, 450}; 451 452static const AVClass photocd_class = { 453 .class_name = "photocd", 454 .item_name = av_default_item_name, 455 .option = options, 456 .version = LIBAVUTIL_VERSION_INT, 457}; 458 459const FFCodec ff_photocd_decoder = { 460 .p.name = "photocd", 461 .p.type = AVMEDIA_TYPE_VIDEO, 462 .p.id = AV_CODEC_ID_PHOTOCD, 463 .priv_data_size = sizeof(PhotoCDContext), 464 .p.priv_class = &photocd_class, 465 .init = photocd_decode_init, 466 .close = photocd_decode_close, 467 FF_CODEC_DECODE_CB(photocd_decode_frame), 468 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, 469 .p.long_name = NULL_IF_CONFIG_SMALL("Kodak Photo CD"), 470 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 471}; 472