Add const where appropriate, also gets rid of a compiler warning.
[mplayer/glamo.git] / libvo / spuenc.c
blob670a393bc2bb385b762afe502a0548b2386fda76
1 /*
2 * encode a pixmap with RLE
4 * Copyright (C) 2000 Alejandro J. Cura <alecu@protocultura.net>
6 * (modified a bit to work with the dxr3 driver...4/2/2002 cg)
8 * Based on the hard work of:
10 * Samuel Hocevar <sam@via.ecp.fr> and Michel Lespinasse <walken@via.ecp.fr>
12 * This file is part of MPlayer.
14 * MPlayer is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * MPlayer is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include "unistd.h"
32 #include "spuenc.h"
34 static void
35 encode_do_control(int x,int y, encodedata* ed, pixbuf* pb) {
36 int controlstart= ed->count;
37 int x1;
38 int i;
39 unsigned int top, left, bottom, right;
41 top= 450 - pb->y/2;
42 left=(720 / 2) - (pb->x / 2);
43 top= 32;//this forces the first bit to be visible on a TV
44 left= 32;//you could actually pass in x/y and do some nice
45 //calculations for making it look right...
46 bottom= top + pb->y - 1;
47 right= left + pb->x - 1;
49 /* the format of this is well described by a page:
50 * http://members.aol.com/mpucoder/DVD/spu.html
52 * note I changed the layout of commands to turn off the subpic as the
53 * first command, and then turn on the new subpic...this is so we can
54 * leave the subpic on for an arbitrary ammount of time as controlled by
55 * mplayer (ie when we turn on the subpic we don't know how long it should
56 * stay on when using mplayer).
57 * with this layout we turn off the last subpic as we are turning on the
58 * new one.
59 * The original hd it turn on the subpic, and delay the turn off command using
60 * the durration/delay feature.
61 * */
62 /* start at x0+2*/
63 i= controlstart;
64 /* display duration... */
65 // ed->data[i++]= 0x00;
66 // ed->data[i++]= 0x00; //durration before turn off command occurs
67 //in 90000/1024 units
69 /* x1 */
70 // x1=i+4;
71 // ed->data[i++]= x1 >> 8;//location of next command block
72 // ed->data[i++]= x1 & 0xff;
73 /* finish it */
74 // ed->data[i++]= 0x02;//turn off command
75 // ed->data[i++]= 0xff;//end of command block
76 x1= i; //marker for last command block address
78 /* display duration... */
79 ed->data[i++]= 0x00;
80 ed->data[i++]= 0x00; //durration before turn on command occurs
81 //in 90000/1024 units
82 /* x1 */
83 ed->data[i++]= x1 >> 8; //since this is the last command block, this
84 ed->data[i++]= x1 & 0xff;//points back to itself
87 /* 0x01: start displaying */
88 ed->data[i++]= 0x01;
90 /* 0x03: palette info */
91 ed->data[i++]= 0x03;
92 ed->data[i++]= 0x08;
93 ed->data[i++]= 0x7f;
95 * The palette is a coded index (one of 16) 0 is black, 0xf is white
96 * (unless you screw with the default palette)
97 * for what I am doing I only use white.
98 * 7 is lt grey, and 8 is dk grey...
99 * */
100 /* 0x04: transparency info (reversed) */
101 ed->data[i++]= 0x04;
102 ed->data[i++]= 0xFF;//change the opacity values of the color entries
103 ed->data[i++]= 0xF0;//say if you wanted white text on a black backround
104 //note you will have to work harder, by finding the
105 //bounding box of the text, and use a non transparent black palette
106 // entry to fill the backround with, (say color 1 instead of 0)
108 /* 0x05: coordinates */
109 ed->data[i++]= 0x05;
110 ed->data[i++]= left >> 4;
111 ed->data[i++]= ((left&0xf)<<4)+(right>>8);
112 ed->data[i++]= (right&0xff);
113 ed->data[i++]= top >> 4;
114 ed->data[i++]= ((top&0xf)<<4)+(bottom>>8);
115 ed->data[i++]= (bottom&0xff);
117 /* 0x06: both fields' offsets */
118 ed->data[i++]= 0x06;
119 ed->data[i++]= 0x00;
120 ed->data[i++]= 0x04;
121 ed->data[i++]= ed->oddstart >> 8;
122 ed->data[i++]= ed->oddstart & 0xff;
124 /* 0xFF: end sequence */
125 ed->data[i++]= 0xFF;
126 if(! i&1 ) {
127 ed->data[i++]= 0xff;
130 /* x0 */
131 ed->data[2]= (controlstart) >> 8;
132 ed->data[3]= (controlstart) & 0xff;
134 /* packet size */
135 ed->data[0]= i >> 8;
136 ed->data[1]= i & 0xff;
138 ed->count= i;
141 static void
142 encode_put_nibble( encodedata* ed, unsigned char nibble ) {
143 if( ed->nibblewaiting ) {
144 ed->data[ed->count++]|= nibble;
145 ed->nibblewaiting= 0;
146 } else {
147 ed->data[ed->count]= nibble<<4;
148 ed->nibblewaiting= 1;
152 static void
153 encode_pixels( encodedata* ed, int color, int number ) {
154 if(number > 3) {
155 if(number > 15) {
156 encode_put_nibble( ed, 0 );
157 if(number > 63) {
158 encode_put_nibble( ed, (number & 0xC0)>>6 );
161 encode_put_nibble( ed, (number & 0x3C)>>2 );
163 encode_put_nibble( ed, ((number & 0xF)<<2) | color);
166 static void
167 encode_eol( encodedata* ed ) {
168 if( ed->nibblewaiting ) {
169 ed->count++;
170 ed->nibblewaiting= 0;
172 ed->data[ed->count++]= 0x00;
173 ed->data[ed->count++]= 0x00;
176 static void
177 encode_do_row( encodedata* ed, pixbuf* pb, int row ) {
178 int i= 0;
179 unsigned char* pix= pb->pixels + row * pb->x;
180 int color= *pix;
181 int n= 0; /* the number of pixels of this color */
183 while( i++ < pb->x ) {
184 /* FIXME: watch this space for EOL */
185 if( *pix != color || n == 255 ) {
186 encode_pixels( ed, color, n );
187 color= *pix;
188 n= 1;
189 } else {
190 n++;
192 pix++;
195 /* this small optimization: (n>63) can save up to two bytes per line
196 * I wonder if this is compatible with all the hardware... */
197 if( color == 0 && n > 63 ) {
198 encode_eol( ed );
199 } else {
200 encode_pixels( ed, color, n );
203 if( ed->nibblewaiting ) {
204 ed->count++;
205 ed->nibblewaiting= 0;
210 void
211 pixbuf_encode_rle(int x, int y, int w, int h, char *inbuf, int stride,encodedata *ed){
212 pixbuf pb;
213 int i, row;
214 pb.x = w;
215 pb.y = h;
217 pb.pixels = inbuf;
218 ed->count= 4;
219 ed->nibblewaiting= 0;
221 row= 0;
222 for( i= 0; i < pb.y; i++ ) {
223 encode_do_row(ed, &pb, row);
224 row+= 2;
225 if( row > pb.y ) {
226 row= 1;
227 ed->oddstart= ed->count;
230 encode_do_control(x,y, ed, &pb);
234 void
235 pixbuf_load_xpm( pixbuf* pb, char* xpm[] ) {
236 int colors, chrs, l, n;
237 char c[4], table[256];
238 unsigned char *b, *i;
240 sscanf( xpm[0], "%d %d %d %d", &pb->x, &pb->y, &colors, &chrs);
241 if( colors > 4 ) {
242 fprintf( stderr, "the pixmap MUST be 4 colors or less\n");
243 exit (-1);
245 if( chrs != 1 ) {
246 fprintf( stderr, "the XPM format MUST be 1 char per pixel\n");
247 exit (-1);
249 if( pb->x > 0xFFF || pb->y > 0xFFF ) {
250 fprintf( stderr, "the size is excesive\n");
251 exit (-1);
254 for( l=0; l<colors; l++ ) {
255 n= sscanf( xpm[l+1], "%c c #%x", &c[l], &pb->rgb[l]);
256 if( n < 2 ) {
257 /* this one is transparent */
258 pb->rgb[l]=0xff000000;
260 table[(int)c[l]]=l;
263 pb->pixels= malloc( pb->x * pb->y );
264 b= pb->pixels;
266 for( l= colors+1; l <= pb->y + colors; l++ ) {
267 i= xpm[l];
268 while( (int)*i) {
269 *b++ = table[*i++];
274 void
275 pixbuf_delete( pixbuf* pb ) {
276 free( pb->pixels );