blob: 7a01633c9afb237569ef8f04f9261500eb321f6f [file] [log] [blame]
Roberto Togni1dc1ed92003-11-07 22:39:181/*
2 * Quicktime Planar RGB (8BPS) Video Decoder
3 * Copyright (C) 2003 Roberto Togni
4 *
Diego Biurrunb78e7192006-10-07 15:30:465 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
Roberto Togni1dc1ed92003-11-07 22:39:188 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
Diego Biurrunb78e7192006-10-07 15:30:4610 * version 2.1 of the License, or (at your option) any later version.
Roberto Togni1dc1ed92003-11-07 22:39:1811 *
Diego Biurrunb78e7192006-10-07 15:30:4612 * FFmpeg is distributed in the hope that it will be useful,
Roberto Togni1dc1ed92003-11-07 22:39:1813 * 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
Diego Biurrunb78e7192006-10-07 15:30:4618 * License along with FFmpeg; if not, write to the Free Software
Diego Biurrun5509bff2006-01-12 22:43:2619 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Roberto Togni1dc1ed92003-11-07 22:39:1820 */
21
22/**
Diego Biurrunba87f082010-04-20 14:45:3423 * @file
Roberto Togni0f6feb52008-06-07 13:14:4924 * QT 8BPS Video Decoder by Roberto Togni
Roberto Togni1dc1ed92003-11-07 22:39:1825 * For more information about the 8BPS format, visit:
26 * http://www.pcisys.net/~melanson/codecs/
27 *
28 * Supports: PAL8 (RGB 8bpp, paletted)
Paul B Mahol1735ca32023-09-10 20:42:1129 * : GBRP (RGB 24bpp)
30 * : GBRAP (RGB 32bpp, 4th plane is alpha)
Roberto Togni1dc1ed92003-11-07 22:39:1831 */
32
Martin Storsjö1d9c2dc2012-08-06 13:49:3233#include <string.h>
Roberto Togni1dc1ed92003-11-07 22:39:1834
Paul B Mahol1735ca32023-09-10 20:42:1135#include "libavutil/intreadwrite.h"
Martin Storsjö1d9c2dc2012-08-06 13:49:3236#include "libavutil/internal.h"
Roberto Togni1dc1ed92003-11-07 22:39:1837#include "avcodec.h"
Andreas Rheinhardta688f3c2022-03-16 17:18:2838#include "codec_internal.h"
Andreas Rheinhardt7b100832021-03-17 21:43:3239#include "decode.h"
Roberto Togni1dc1ed92003-11-07 22:39:1840
Roberto Togni1dc1ed92003-11-07 22:39:1841typedef struct EightBpsContext {
Paul B Mahol324e8182012-01-26 19:21:1542 AVCodecContext *avctx;
Roberto Togni1dc1ed92003-11-07 22:39:1843
Paul B Mahol1ce19702023-09-10 20:19:1944 uint8_t planes;
45 uint8_t planemap[4];
Anton Khirnov6dbde682023-10-24 13:03:5146
47 uint32_t pal[256];
Roberto Togni1dc1ed92003-11-07 22:39:1848} EightBpsContext;
49
Andreas Rheinhardtce7dbd02022-03-30 19:33:2450static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
Anton Khirnovdf9b9562012-11-13 18:35:2251 int *got_frame, AVPacket *avpkt)
Roberto Togni1dc1ed92003-11-07 22:39:1852{
Paul B Mahol324e8182012-01-26 19:21:1553 const uint8_t *buf = avpkt->data;
54 int buf_size = avpkt->size;
55 EightBpsContext * const c = avctx->priv_data;
Paul B Mahol1ce19702023-09-10 20:19:1956 const uint8_t *encoded = buf;
57 uint8_t *pixptr, *pixptr_end;
Paul B Mahol324e8182012-01-26 19:21:1558 unsigned int height = avctx->height; // Real image height
59 unsigned int dlen, p, row;
Paul B Mahol1ce19702023-09-10 20:19:1960 const uint8_t *lp, *dp, *ep;
61 uint8_t count;
Paul B Mahol1735ca32023-09-10 20:42:1162 const uint8_t *planemap = c->planemap;
63 unsigned int planes = c->planes;
Anton Khirnov313da472012-11-14 07:59:0364 int ret;
Diego Biurrun115329f2005-12-17 18:14:3865
Michael Niedermayer5db09572024-02-25 21:06:4866 if (buf_size < planes * height * (2 + 2*((avctx->width+128)/129)))
Michael Niedermayer2316d5e2022-08-22 20:10:0967 return AVERROR_INVALIDDATA;
68
Clément Bœsch1ec94b02013-03-12 07:41:5369 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
Anton Khirnov313da472012-11-14 07:59:0370 return ret;
Roberto Togni1dc1ed92003-11-07 22:39:1871
Luca Barbatobd7b4da2013-07-22 21:26:0572 ep = encoded + buf_size;
73
Paul B Mahol324e8182012-01-26 19:21:1574 /* Set data pointer after line lengths */
75 dp = encoded + planes * (height << 1);
Roberto Togni1dc1ed92003-11-07 22:39:1876
Paul B Mahol324e8182012-01-26 19:21:1577 for (p = 0; p < planes; p++) {
Paul B Mahol1735ca32023-09-10 20:42:1178 const int pi = planemap[p];
Paul B Mahol324e8182012-01-26 19:21:1579 /* Lines length pointer for this plane */
80 lp = encoded + p * (height << 1);
Roberto Togni1dc1ed92003-11-07 22:39:1881
Paul B Mahol324e8182012-01-26 19:21:1582 /* Decode a plane */
83 for (row = 0; row < height; row++) {
Paul B Mahol1735ca32023-09-10 20:42:1184 pixptr = frame->data[pi] + row * frame->linesize[pi];
85 pixptr_end = pixptr + frame->linesize[pi];
Luca Barbatobd7b4da2013-07-22 21:26:0586 if (ep - lp < row * 2 + 2)
87 return AVERROR_INVALIDDATA;
Paul B Mahol1735ca32023-09-10 20:42:1188 dlen = AV_RB16(lp + row * 2);
Paul B Mahol324e8182012-01-26 19:21:1589 /* Decode a row of this plane */
90 while (dlen > 0) {
Luca Barbatobd7b4da2013-07-22 21:26:0591 if (ep - dp <= 1)
Anton Khirnov313da472012-11-14 07:59:0392 return AVERROR_INVALIDDATA;
Paul B Mahol324e8182012-01-26 19:21:1593 if ((count = *dp++) <= 127) {
94 count++;
95 dlen -= count + 1;
Paul B Mahol1735ca32023-09-10 20:42:1196 if (pixptr_end - pixptr < count)
Paul B Mahol324e8182012-01-26 19:21:1597 break;
Luca Barbatobd7b4da2013-07-22 21:26:0598 if (ep - dp < count)
Anton Khirnov313da472012-11-14 07:59:0399 return AVERROR_INVALIDDATA;
Paul B Mahol1735ca32023-09-10 20:42:11100 memcpy(pixptr, dp, count);
101 pixptr += count;
102 dp += count;
Paul B Mahol324e8182012-01-26 19:21:15103 } else {
104 count = 257 - count;
Paul B Mahol1735ca32023-09-10 20:42:11105 if (pixptr_end - pixptr < count)
Paul B Mahol324e8182012-01-26 19:21:15106 break;
Paul B Mahol1735ca32023-09-10 20:42:11107 memset(pixptr, dp[0], count);
108 pixptr += count;
Paul B Mahol324e8182012-01-26 19:21:15109 dp++;
110 dlen -= 2;
Diego Biurrunbb270c02005-12-22 01:10:11111 }
Paul B Mahol324e8182012-01-26 19:21:15112 }
113 }
114 }
115
Carl Eugen Hoyos54bbe3e2014-03-11 19:09:07116 if (avctx->bits_per_coded_sample <= 8) {
Anton Khirnov6dbde682023-10-24 13:03:51117 ff_copy_palette(c->pal, avpkt, avctx);
Anton Khirnov6dbde682023-10-24 13:03:51118
119 memcpy(frame->data[1], c->pal, AVPALETTE_SIZE);
Paul B Mahol324e8182012-01-26 19:21:15120 }
Kostya Shishkov2d8591c2011-04-09 13:49:51121
Anton Khirnovdf9b9562012-11-13 18:35:22122 *got_frame = 1;
Roberto Togni1dc1ed92003-11-07 22:39:18123
Paul B Mahol324e8182012-01-26 19:21:15124 /* always report that the buffer was completely consumed */
125 return buf_size;
Roberto Togni1dc1ed92003-11-07 22:39:18126}
127
Zuxy Meng98a6fff2008-03-21 03:11:20128static av_cold int decode_init(AVCodecContext *avctx)
Roberto Togni1dc1ed92003-11-07 22:39:18129{
Paul B Mahol324e8182012-01-26 19:21:15130 EightBpsContext * const c = avctx->priv_data;
Roberto Togni1dc1ed92003-11-07 22:39:18131
Paul B Mahol324e8182012-01-26 19:21:15132 c->avctx = avctx;
Roberto Togni1dc1ed92003-11-07 22:39:18133
Paul B Mahol324e8182012-01-26 19:21:15134 switch (avctx->bits_per_coded_sample) {
135 case 8:
Anton Khirnov716d4132012-10-06 10:10:34136 avctx->pix_fmt = AV_PIX_FMT_PAL8;
Paul B Mahol324e8182012-01-26 19:21:15137 c->planes = 1;
138 c->planemap[0] = 0; // 1st plane is palette indexes
139 break;
140 case 24:
Paul B Mahol1735ca32023-09-10 20:42:11141 avctx->pix_fmt = AV_PIX_FMT_GBRP;
Paul B Mahol324e8182012-01-26 19:21:15142 c->planes = 3;
143 c->planemap[0] = 2; // 1st plane is red
Paul B Mahol1735ca32023-09-10 20:42:11144 c->planemap[1] = 0; // 2nd plane is green
145 c->planemap[2] = 1; // 3rd plane is blue
Paul B Mahol324e8182012-01-26 19:21:15146 break;
147 case 32:
Paul B Mahol1735ca32023-09-10 20:42:11148 avctx->pix_fmt = AV_PIX_FMT_GBRAP;
Paul B Mahol324e8182012-01-26 19:21:15149 c->planes = 4;
Paul B Mahol324e8182012-01-26 19:21:15150 break;
151 default:
152 av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n",
153 avctx->bits_per_coded_sample);
Anton Khirnov313da472012-11-14 07:59:03154 return AVERROR_INVALIDDATA;
Paul B Mahol324e8182012-01-26 19:21:15155 }
Roberto Togni1dc1ed92003-11-07 22:39:18156
Paul B Mahol1735ca32023-09-10 20:42:11157 if (avctx->pix_fmt == AV_PIX_FMT_GBRAP) {
158 c->planemap[0] = 2; // 1st plane is red
159 c->planemap[1] = 0; // 2nd plane is green
160 c->planemap[2] = 1; // 3rd plane is blue
161 c->planemap[3] = 3; // 4th plane is alpha
Janne Grunaue8c0def2013-07-19 11:51:51162 }
Paul B Mahol324e8182012-01-26 19:21:15163 return 0;
Roberto Togni1dc1ed92003-11-07 22:39:18164}
165
Andreas Rheinhardt20f97272022-03-16 20:09:54166const FFCodec ff_eightbps_decoder = {
167 .p.name = "8bps",
Andreas Rheinhardt48286d42022-08-29 11:38:02168 CODEC_LONG_NAME("QuickTime 8BPS video"),
Andreas Rheinhardt20f97272022-03-16 20:09:54169 .p.type = AVMEDIA_TYPE_VIDEO,
170 .p.id = AV_CODEC_ID_8BPS,
Anton Khirnovec6402b2011-07-17 10:54:31171 .priv_data_size = sizeof(EightBpsContext),
172 .init = decode_init,
Andreas Rheinhardt4243da42022-03-30 21:28:24173 FF_CODEC_DECODE_CB(decode_frame),
Andreas Rheinhardt20f97272022-03-16 20:09:54174 .p.capabilities = AV_CODEC_CAP_DR1,
Roberto Togni1dc1ed92003-11-07 22:39:18175};