Statistics
| Branch: | Revision:

ffmpeg / libavcodec / 8bps.c @ ab35de18

History | View | Annotate | Download (5.29 KB)

1
/*
2
 * Quicktime Planar RGB (8BPS) Video Decoder
3
 * Copyright (C) 2003 Roberto Togni
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *
19
 */
20

    
21
/**
22
 * @file 8bps.c
23
 * QT 8BPS Video Decoder by Roberto Togni <rtogni at bresciaonline dot it>
24
 * For more information about the 8BPS format, visit:
25
 *   http://www.pcisys.net/~melanson/codecs/
26
 *
27
 * Supports: PAL8 (RGB 8bpp, paletted)
28
 *         : BGR24 (RGB 24bpp) (can also output it as RGBA32)
29
 *         : RGBA32 (RGB 32bpp, 4th plane is probably alpha and it's ignored)
30
 *
31
 */
32

    
33
#include <stdio.h>
34
#include <stdlib.h>
35

    
36
#include "common.h"
37
#include "avcodec.h"
38

    
39

    
40
const enum PixelFormat pixfmt_rgb24[] = {PIX_FMT_BGR24, PIX_FMT_RGBA32, -1};
41

    
42
/*
43
 * Decoder context
44
 */
45
typedef struct EightBpsContext {
46

    
47
        AVCodecContext *avctx;
48
        AVFrame pic;
49

    
50
        unsigned char planes;
51
        unsigned char planemap[4];
52
} EightBpsContext;
53

    
54

    
55
/*
56
 *
57
 * Decode a frame
58
 *
59
 */
60
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
61
{
62
        EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
63
        unsigned char *encoded = (unsigned char *)buf;
64
        unsigned char *pixptr;
65
        unsigned int height = avctx->height; // Real image height
66
        unsigned int dlen, p, row;
67
        unsigned char *lp, *dp;
68
        unsigned char count;
69
        unsigned int px_inc;
70
        unsigned int planes = c->planes;
71
        unsigned char *planemap = c->planemap;
72
  
73
  
74
        /* no supplementary picture */
75
        if (buf_size == 0)
76
                return 0;
77

    
78
        if(c->pic.data[0])
79
                avctx->release_buffer(avctx, &c->pic);
80

    
81
        c->pic.reference = 0;
82
        c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
83
        if(avctx->get_buffer(avctx, &c->pic) < 0){
84
                av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
85
                return -1;
86
        }
87

    
88
        /* Set data pointer after line lengths */
89
        dp = encoded + planes * (height << 1);
90

    
91
        /* Ignore alpha plane, don't know what to do with it */
92
        if (planes == 4)
93
                planes--;
94

    
95
        px_inc = planes + (avctx->pix_fmt == PIX_FMT_RGBA32);
96

    
97
        for (p = 0; p < planes; p++) {
98
                /* Lines length pointer for this plane */
99
                lp = encoded + p * (height << 1);
100

    
101
                /* Decode a plane */
102
                for(row = 0; row < height; row++) {
103
                        pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
104
                        dlen = be2me_16(*(unsigned short *)(lp+row*2));
105
                        /* Decode a row of this plane */
106
                        while(dlen > 0) {
107
                                if ((count = *dp++) <= 127) {
108
                                        count++;
109
                                        dlen -= count + 1;
110
                                        while(count--) {
111
                                                *pixptr = *dp++;
112
                                                pixptr += px_inc;
113
                                        }
114
                                } else {
115
                                        count = 257 - count;
116
                                        while(count--) {
117
                                                *pixptr = *dp;
118
                                                pixptr += px_inc;
119
                                        }
120
                                        dp++;
121
                                        dlen -= 2;
122
                                }
123
                        }
124
                }
125
        }
126

    
127
        if (avctx->palctrl) {
128
                memcpy (c->pic.data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
129
                if (avctx->palctrl->palette_changed) {
130
                        c->pic.palette_has_changed = 1;
131
                        avctx->palctrl->palette_changed = 0;
132
                } else
133
                        c->pic.palette_has_changed = 0;
134
        }
135

    
136
        *data_size = sizeof(AVFrame);
137
        *(AVFrame*)data = c->pic;
138

    
139
        /* always report that the buffer was completely consumed */
140
        return buf_size;
141
}
142

    
143

    
144
/*
145
 *
146
 * Init 8BPS decoder
147
 *
148
 */
149
static int decode_init(AVCodecContext *avctx)
150
{
151
        EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
152

    
153
        c->avctx = avctx;
154
        avctx->has_b_frames = 0;
155

    
156
        c->pic.data[0] = NULL;
157

    
158
        switch (avctx->bits_per_sample) {
159
                case 8:
160
                        avctx->pix_fmt = PIX_FMT_PAL8;
161
                        c->planes = 1;
162
                        c->planemap[0] = 0; // 1st plane is palette indexes
163
                        if (avctx->palctrl == NULL) {
164
                                av_log(avctx, AV_LOG_ERROR, "Error: PAL8 format but no palette from demuxer.\n");
165
                                return -1;
166
                        }
167
                        break;
168
                case 24:
169
                        avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24);
170
                        c->planes = 3;
171
                        c->planemap[0] = 2; // 1st plane is red
172
                        c->planemap[1] = 1; // 2nd plane is green
173
                        c->planemap[2] = 0; // 3rd plane is blue
174
                        break;
175
                case 32:
176
                        avctx->pix_fmt = PIX_FMT_RGBA32;
177
                        c->planes = 4;
178
#ifdef WORDS_BIGENDIAN
179
                        c->planemap[0] = 1; // 1st plane is red
180
                        c->planemap[1] = 2; // 2nd plane is green
181
                        c->planemap[2] = 3; // 3rd plane is blue
182
                        c->planemap[3] = 0; // 4th plane is alpha???
183
#else
184
                        c->planemap[0] = 2; // 1st plane is red
185
                        c->planemap[1] = 1; // 2nd plane is green
186
                        c->planemap[2] = 0; // 3rd plane is blue
187
                        c->planemap[3] = 3; // 4th plane is alpha???
188
#endif
189
                        break;
190
                default:
191
                        av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n", avctx->bits_per_sample);
192
                        return -1;
193
        }
194

    
195
  return 0;
196
}
197

    
198

    
199

    
200

    
201
/*
202
 *
203
 * Uninit 8BPS decoder
204
 *
205
 */
206
static int decode_end(AVCodecContext *avctx)
207
{
208
        EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
209

    
210
        if (c->pic.data[0])
211
                avctx->release_buffer(avctx, &c->pic);
212

    
213
        return 0;
214
}
215

    
216

    
217

    
218
AVCodec eightbps_decoder = {
219
        "8bps",
220
        CODEC_TYPE_VIDEO,
221
        CODEC_ID_8BPS,
222
        sizeof(EightBpsContext),
223
        decode_init,
224
        NULL,
225
        decode_end,
226
        decode_frame,
227
        CODEC_CAP_DR1,
228
};