blob: 95e811a43cd00ea937c8849b472959e71da21a0f [file] [log] [blame]
Roberto Togni1dc1ed92003-11-07 22:39:181/*
2 * Quicktime Planar RGB (8BPS) Video Decoder
3 * Copyright (C) 2003 Roberto Togni
4 *
Mans Rullgard2912e872011-03-18 17:35:105 * This file is part of Libav.
Diego Biurrunb78e7192006-10-07 15:30:466 *
Mans Rullgard2912e872011-03-18 17:35:107 * Libav 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 *
Mans Rullgard2912e872011-03-18 17:35:1012 * Libav 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
Mans Rullgard2912e872011-03-18 17:35:1018 * License along with Libav; 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)
Diego Biurrun71e445f2007-02-07 01:48:0929 * : BGR24 (RGB 24bpp) (can also output it as RGB32)
30 * : RGB32 (RGB 32bpp, 4th plane is probably alpha and it's ignored)
Roberto Togni1dc1ed92003-11-07 22:39:1831 *
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
Martin Storsjö1d9c2dc2012-08-06 13:49:3236#include <string.h>
Roberto Togni1dc1ed92003-11-07 22:39:1837
Martin Storsjö1d9c2dc2012-08-06 13:49:3238#include "libavutil/internal.h"
Diego Biurrun6a5d31a2009-01-11 22:19:4839#include "libavutil/intreadwrite.h"
Roberto Togni1dc1ed92003-11-07 22:39:1840#include "avcodec.h"
41
42
Anton Khirnov716d4132012-10-06 10:10:3443static const enum AVPixelFormat pixfmt_rgb24[] = {
44 AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE };
Roberto Togni1dc1ed92003-11-07 22:39:1845
46/*
47 * Decoder context
48 */
49typedef struct EightBpsContext {
Paul B Mahol324e8182012-01-26 19:21:1550 AVCodecContext *avctx;
51 AVFrame pic;
Roberto Togni1dc1ed92003-11-07 22:39:1852
Paul B Mahol324e8182012-01-26 19:21:1553 unsigned char planes;
54 unsigned char planemap[4];
Roberto Togni1dc1ed92003-11-07 22:39:1855
Paul B Mahol324e8182012-01-26 19:21:1556 uint32_t pal[256];
Roberto Togni1dc1ed92003-11-07 22:39:1857} EightBpsContext;
58
59
60/*
61 *
62 * Decode a frame
63 *
64 */
Paul B Mahol324e8182012-01-26 19:21:1565static int decode_frame(AVCodecContext *avctx, void *data,
66 int *data_size, AVPacket *avpkt)
Roberto Togni1dc1ed92003-11-07 22:39:1867{
Paul B Mahol324e8182012-01-26 19:21:1568 const uint8_t *buf = avpkt->data;
69 int buf_size = avpkt->size;
70 EightBpsContext * const c = avctx->priv_data;
71 const unsigned char *encoded = buf;
72 unsigned char *pixptr, *pixptr_end;
73 unsigned int height = avctx->height; // Real image height
74 unsigned int dlen, p, row;
75 const unsigned char *lp, *dp;
76 unsigned char count;
77 unsigned int px_inc;
78 unsigned int planes = c->planes;
79 unsigned char *planemap = c->planemap;
Diego Biurrun115329f2005-12-17 18:14:3880
Paul B Mahol324e8182012-01-26 19:21:1581 if (c->pic.data[0])
82 avctx->release_buffer(avctx, &c->pic);
Roberto Togni1dc1ed92003-11-07 22:39:1883
Paul B Mahol324e8182012-01-26 19:21:1584 c->pic.reference = 0;
85 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
86 if (avctx->get_buffer(avctx, &c->pic) < 0){
87 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
88 return -1;
89 }
Roberto Togni1dc1ed92003-11-07 22:39:1890
Paul B Mahol324e8182012-01-26 19:21:1591 /* Set data pointer after line lengths */
92 dp = encoded + planes * (height << 1);
Roberto Togni1dc1ed92003-11-07 22:39:1893
Paul B Mahol324e8182012-01-26 19:21:1594 /* Ignore alpha plane, don't know what to do with it */
95 if (planes == 4)
96 planes--;
Roberto Togni1dc1ed92003-11-07 22:39:1897
Anton Khirnov716d4132012-10-06 10:10:3498 px_inc = planes + (avctx->pix_fmt == AV_PIX_FMT_RGB32);
Roberto Togni1dc1ed92003-11-07 22:39:1899
Paul B Mahol324e8182012-01-26 19:21:15100 for (p = 0; p < planes; p++) {
101 /* Lines length pointer for this plane */
102 lp = encoded + p * (height << 1);
Roberto Togni1dc1ed92003-11-07 22:39:18103
Paul B Mahol324e8182012-01-26 19:21:15104 /* Decode a plane */
105 for (row = 0; row < height; row++) {
106 pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
107 pixptr_end = pixptr + c->pic.linesize[0];
108 dlen = av_be2ne16(*(const unsigned short *)(lp + row * 2));
109 /* Decode a row of this plane */
110 while (dlen > 0) {
111 if (dp + 1 >= buf + buf_size)
112 return -1;
113 if ((count = *dp++) <= 127) {
114 count++;
115 dlen -= count + 1;
116 if (pixptr + count * px_inc > pixptr_end)
117 break;
118 if (dp + count > buf + buf_size)
119 return -1;
120 while (count--) {
121 *pixptr = *dp++;
122 pixptr += px_inc;
123 }
124 } else {
125 count = 257 - count;
126 if (pixptr + count * px_inc > pixptr_end)
127 break;
128 while (count--) {
129 *pixptr = *dp;
130 pixptr += px_inc;
131 }
132 dp++;
133 dlen -= 2;
Diego Biurrunbb270c02005-12-22 01:10:11134 }
Paul B Mahol324e8182012-01-26 19:21:15135 }
136 }
137 }
138
139 if (avctx->bits_per_coded_sample <= 8) {
140 const uint8_t *pal = av_packet_get_side_data(avpkt,
141 AV_PKT_DATA_PALETTE,
142 NULL);
143 if (pal) {
144 c->pic.palette_has_changed = 1;
145 memcpy(c->pal, pal, AVPALETTE_SIZE);
Diego Biurrunbb270c02005-12-22 01:10:11146 }
Roberto Togni1dc1ed92003-11-07 22:39:18147
Paul B Mahol324e8182012-01-26 19:21:15148 memcpy (c->pic.data[1], c->pal, AVPALETTE_SIZE);
149 }
Kostya Shishkov2d8591c2011-04-09 13:49:51150
Paul B Mahol324e8182012-01-26 19:21:15151 *data_size = sizeof(AVFrame);
152 *(AVFrame*)data = c->pic;
Roberto Togni1dc1ed92003-11-07 22:39:18153
Paul B Mahol324e8182012-01-26 19:21:15154 /* always report that the buffer was completely consumed */
155 return buf_size;
Roberto Togni1dc1ed92003-11-07 22:39:18156}
157
158
159/*
160 *
161 * Init 8BPS decoder
162 *
163 */
Zuxy Meng98a6fff2008-03-21 03:11:20164static av_cold int decode_init(AVCodecContext *avctx)
Roberto Togni1dc1ed92003-11-07 22:39:18165{
Paul B Mahol324e8182012-01-26 19:21:15166 EightBpsContext * const c = avctx->priv_data;
Roberto Togni1dc1ed92003-11-07 22:39:18167
Paul B Mahol324e8182012-01-26 19:21:15168 c->avctx = avctx;
169 c->pic.data[0] = NULL;
Roberto Togni1dc1ed92003-11-07 22:39:18170
Paul B Mahol324e8182012-01-26 19:21:15171 switch (avctx->bits_per_coded_sample) {
172 case 8:
Anton Khirnov716d4132012-10-06 10:10:34173 avctx->pix_fmt = AV_PIX_FMT_PAL8;
Paul B Mahol324e8182012-01-26 19:21:15174 c->planes = 1;
175 c->planemap[0] = 0; // 1st plane is palette indexes
176 break;
177 case 24:
178 avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24);
179 c->planes = 3;
180 c->planemap[0] = 2; // 1st plane is red
181 c->planemap[1] = 1; // 2nd plane is green
182 c->planemap[2] = 0; // 3rd plane is blue
183 break;
184 case 32:
Anton Khirnov716d4132012-10-06 10:10:34185 avctx->pix_fmt = AV_PIX_FMT_RGB32;
Paul B Mahol324e8182012-01-26 19:21:15186 c->planes = 4;
Måns Rullgård63613fe62009-07-26 12:20:04187#if HAVE_BIGENDIAN
Paul B Mahol324e8182012-01-26 19:21:15188 c->planemap[0] = 1; // 1st plane is red
189 c->planemap[1] = 2; // 2nd plane is green
190 c->planemap[2] = 3; // 3rd plane is blue
191 c->planemap[3] = 0; // 4th plane is alpha???
Roberto Togni1dc1ed92003-11-07 22:39:18192#else
Paul B Mahol324e8182012-01-26 19:21:15193 c->planemap[0] = 2; // 1st plane is red
194 c->planemap[1] = 1; // 2nd plane is green
195 c->planemap[2] = 0; // 3rd plane is blue
196 c->planemap[3] = 3; // 4th plane is alpha???
Roberto Togni1dc1ed92003-11-07 22:39:18197#endif
Paul B Mahol324e8182012-01-26 19:21:15198 break;
199 default:
200 av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n",
201 avctx->bits_per_coded_sample);
202 return -1;
203 }
Roberto Togni1dc1ed92003-11-07 22:39:18204
Paul B Mahol324e8182012-01-26 19:21:15205 return 0;
Roberto Togni1dc1ed92003-11-07 22:39:18206}
207
208
209
210
211/*
212 *
213 * Uninit 8BPS decoder
214 *
215 */
Zuxy Meng98a6fff2008-03-21 03:11:20216static av_cold int decode_end(AVCodecContext *avctx)
Roberto Togni1dc1ed92003-11-07 22:39:18217{
Paul B Mahol324e8182012-01-26 19:21:15218 EightBpsContext * const c = avctx->priv_data;
Roberto Togni1dc1ed92003-11-07 22:39:18219
Paul B Mahol324e8182012-01-26 19:21:15220 if (c->pic.data[0])
221 avctx->release_buffer(avctx, &c->pic);
Roberto Togni1dc1ed92003-11-07 22:39:18222
Paul B Mahol324e8182012-01-26 19:21:15223 return 0;
Roberto Togni1dc1ed92003-11-07 22:39:18224}
225
226
227
Diego Elio Pettenòd36beb32011-01-25 21:40:11228AVCodec ff_eightbps_decoder = {
Anton Khirnovec6402b2011-07-17 10:54:31229 .name = "8bps",
230 .type = AVMEDIA_TYPE_VIDEO,
Anton Khirnov36ef5362012-08-05 09:11:04231 .id = AV_CODEC_ID_8BPS,
Anton Khirnovec6402b2011-07-17 10:54:31232 .priv_data_size = sizeof(EightBpsContext),
233 .init = decode_init,
234 .close = decode_end,
235 .decode = decode_frame,
236 .capabilities = CODEC_CAP_DR1,
Diego Biurrun933a6fd2011-08-03 21:27:50237 .long_name = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"),
Roberto Togni1dc1ed92003-11-07 22:39:18238};