dx50 = DX50
[mplayer/glamo.git] / libmpcodecs / vd_qt8bps.c
blob1061d85d759014170a79471ad2cff00628199aeb
1 /*
3 * QuickTime 8BPS decoder for Mplayer
4 * (c) 2003 Roberto Togni
6 * Fourcc: 8BPS
8 * Supports 8bpp (paletted), 24bpp and 32bpp (4th plane ignored)
12 #include <stdio.h>
13 #include <stdlib.h>
15 #include "config.h"
16 #include "bswap.h"
18 #include "mp_msg.h"
20 #include "vd_internal.h"
23 static vd_info_t info = {
24 "8BPS Video decoder",
25 "qt8bps",
26 "Roberto Togni",
27 "Roberto Togni",
28 "native codec"
31 LIBVD_EXTERN(qt8bps)
35 * Decoder context
37 typedef struct {
38 unsigned char planes;
39 unsigned char planemap[4];
40 unsigned char *palette;
41 } qt8bps_context_t;
45 * Internal function prototypes
49 // to set/get/query special features/parameters
50 static int control(sh_video_t *sh,int cmd,void* arg,...)
52 qt8bps_context_t *hc = (qt8bps_context_t *) sh->context; // Decoder context
54 if (cmd == VDCTRL_QUERY_FORMAT)
55 switch (hc->planes) {
56 case 1:
57 if (*((int*)arg) == IMGFMT_BGR8)
58 return CONTROL_TRUE;
59 else
60 return CONTROL_FALSE;
61 break;
62 case 3:
63 case 4:
64 if ((*((int*)arg) == IMGFMT_BGR24) || (*((int*)arg) == IMGFMT_BGR32))
65 return CONTROL_TRUE;
66 else
67 return CONTROL_FALSE;
68 break;
69 default:
70 return CONTROL_FALSE;
73 return CONTROL_UNKNOWN;
79 * Init 8BPS decoder
82 static int init(sh_video_t *sh)
84 int vo_ret; // Video output init ret value
85 qt8bps_context_t *hc; // Decoder context
86 BITMAPINFOHEADER *bih = sh->bih;
88 if ((hc = malloc(sizeof(qt8bps_context_t))) == NULL) {
89 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for 8BPS decoder context.\n");
90 return 0;
93 sh->context = (void *)hc;
94 hc->palette = NULL;
96 switch (bih->biBitCount) {
97 case 8:
98 hc->planes = 1;
99 hc->planemap[0] = 0; // 1st plane is palette indexes
100 if (bih->biSize > sizeof(BITMAPINFOHEADER)) {
101 hc->palette = (unsigned char *)malloc(256*4);
102 memcpy(hc->palette, (unsigned char*)bih + sizeof(BITMAPINFOHEADER), 256*4);
104 break;
105 case 24:
106 hc->planes = 3;
107 hc->planemap[0] = 2; // 1st plane is red
108 hc->planemap[1] = 1; // 2nd plane is green
109 hc->planemap[2] = 0; // 3rd plane is blue
110 break;
111 case 32:
112 hc->planes = 4;
113 hc->planemap[0] = 2; // 1st plane is red
114 hc->planemap[1] = 1; // 2nd plane is green
115 hc->planemap[2] = 0; // 3rd plane is blue
116 hc->planemap[3] = 3; // 4th plane is alpha???
117 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[8BPS] Ignoring 4th (alpha?) plane.\n");
118 break;
119 default:
120 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[8BPS] Unsupported color depth: %u.\n", bih->biBitCount);
121 return 0;
125 * Initialize video output device
127 vo_ret = mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_BGR24);
129 return vo_ret;
137 * Uninit 8BPS decoder
140 static void uninit(sh_video_t *sh)
142 qt8bps_context_t *hc = (qt8bps_context_t *) sh->context; // Decoder context
144 if (sh->context) {
145 if (hc->palette)
146 free (hc->palette);
147 free(sh->context);
155 * Decode a frame
158 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
160 mp_image_t* mpi;
161 unsigned char *encoded = (unsigned char *)data;
162 qt8bps_context_t *hc = (qt8bps_context_t *) sh->context; // Decoder context
163 unsigned char *outptr, *pixptr;
164 unsigned int height = sh->disp_h; // Real image height
165 unsigned int dlen, p, row;
166 unsigned char *lp, *dp;
167 unsigned char count;
168 unsigned int px_inc;
169 unsigned int planes = hc->planes;
170 unsigned char *planemap = hc->planemap;
173 // Skipped frame
174 if(len <= 0)
175 return NULL;
177 /* Get output image buffer */
178 mpi=mpcodecs_get_image(sh, MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE, sh->disp_w, sh->disp_h);
179 if (!mpi) {
180 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate mpi image for 8BPS codec.\n");
181 return NULL;
184 outptr = mpi->planes[0]; // Output image pointer
185 px_inc = mpi->bpp/8;
187 /* Set data pointer after line lengths */
188 dp = encoded + hc->planes*(height << 1);
190 /* Ignore alpha plane, don't know what to do with it */
191 if (planes == 4)
192 planes--;
194 for (p = 0; p < planes; p++) {
195 /* Lines length pointer for this plane */
196 lp = encoded + p*(height << 1);
198 /* Decode a plane */
199 for(row = 0; row < height; row++) {
200 pixptr = outptr + row * mpi->stride[0] + planemap[p];
201 dlen = be2me_16(*(unsigned short *)(lp+row*2));
202 /* Decode a row of this plane */
203 while(dlen > 0) {
204 if ((count = *dp++) <= 127) {
205 count++;
206 dlen -= count + 1;
207 while(count--) {
208 *pixptr = *dp++;
209 pixptr += px_inc;
211 } else {
212 count = 257 - count;
213 while(count--) {
214 *pixptr = *dp;
215 pixptr += px_inc;
217 dp++;
218 dlen -= 2;
224 if (hc->palette)
225 mpi->planes[1] = hc->palette;
227 return mpi;