2 * subpic_encode.c - encodes 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 program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 encode_do_control(int x
,int y
, encodedata
* ed
, pixbuf
* pb
) {
35 int controlstart
= ed
->count
;
38 unsigned int top
, left
, bottom
, right
;
41 left
=(720 / 2) - (pb
->x
/ 2);
42 top
= 32;//this forces the first bit to be visible on a TV
43 left
= 32;//you could actually pass in x/y and do some nice
44 //calculations for making it look right...
45 bottom
= top
+ pb
->y
- 1;
46 right
= left
+ pb
->x
- 1;
48 /* the format of this is well described by a page:
49 * http://members.aol.com/mpucoder/DVD/spu.html
51 * note I changed the layout of commands to turn off the subpic as the
52 * first command, and then turn on the new subpic...this is so we can
53 * leave the subpic on for an arbitrary ammount of time as controlled by
54 * mplayer (ie when we turn on the subpic we don't know how long it should
55 * stay on when using mplayer).
56 * with this layout we turn off the last subpic as we are turning on the
58 * The original hd it turn on the subpic, and delay the turn off command using
59 * the durration/delay feature.
63 /* display duration... */
64 // ed->data[i++]= 0x00;
65 // ed->data[i++]= 0x00; //durration before turn off command occurs
70 // ed->data[i++]= x1 >> 8;//location of next command block
71 // ed->data[i++]= x1 & 0xff;
73 // ed->data[i++]= 0x02;//turn off command
74 // ed->data[i++]= 0xff;//end of command block
75 x1
= i
; //marker for last command block address
77 /* display duration... */
79 ed
->data
[i
++]= 0x00; //durration before turn on command occurs
82 ed
->data
[i
++]= x1
>> 8; //since this is the last command block, this
83 ed
->data
[i
++]= x1
& 0xff;//points back to itself
86 /* 0x01: start displaying */
89 /* 0x03: palette info */
94 * The palette is a coded index (one of 16) 0 is black, 0xf is white
95 * (unless you screw with the default palette)
96 * for what I am doing I only use white.
97 * 7 is lt grey, and 8 is dk grey...
99 /* 0x04: transparency info (reversed) */
101 ed
->data
[i
++]= 0xFF;//change the opacity values of the color entries
102 ed
->data
[i
++]= 0xF0;//say if you wanted white text on a black backround
103 //note you will have to work harder, by finding the
104 //bounding box of the text, and use a non transparent black palette
105 // entry to fill the backround with, (say color 1 instead of 0)
107 /* 0x05: coordinates */
109 ed
->data
[i
++]= left
>> 4;
110 ed
->data
[i
++]= ((left
&0xf)<<4)+(right
>>8);
111 ed
->data
[i
++]= (right
&0xff);
112 ed
->data
[i
++]= top
>> 4;
113 ed
->data
[i
++]= ((top
&0xf)<<4)+(bottom
>>8);
114 ed
->data
[i
++]= (bottom
&0xff);
116 /* 0x06: both fields' offsets */
120 ed
->data
[i
++]= ed
->oddstart
>> 8;
121 ed
->data
[i
++]= ed
->oddstart
& 0xff;
123 /* 0xFF: end sequence */
130 ed
->data
[2]= (controlstart
) >> 8;
131 ed
->data
[3]= (controlstart
) & 0xff;
135 ed
->data
[1]= i
& 0xff;
141 encode_put_nibble( encodedata
* ed
, unsigned char nibble
) {
142 if( ed
->nibblewaiting
) {
143 ed
->data
[ed
->count
++]|= nibble
;
144 ed
->nibblewaiting
= 0;
146 ed
->data
[ed
->count
]= nibble
<<4;
147 ed
->nibblewaiting
= 1;
152 encode_pixels( encodedata
* ed
, int color
, int number
) {
155 encode_put_nibble( ed
, 0 );
157 encode_put_nibble( ed
, (number
& 0xC0)>>6 );
160 encode_put_nibble( ed
, (number
& 0x3C)>>2 );
162 encode_put_nibble( ed
, ((number
& 0xF)<<2) | color
);
166 encode_eol( encodedata
* ed
) {
167 if( ed
->nibblewaiting
) {
169 ed
->nibblewaiting
= 0;
171 ed
->data
[ed
->count
++]= 0x00;
172 ed
->data
[ed
->count
++]= 0x00;
176 encode_do_row( encodedata
* ed
, pixbuf
* pb
, int row
) {
178 unsigned char* pix
= pb
->pixels
+ row
* pb
->x
;
180 int n
= 0; /* the number of pixels of this color */
182 while( i
++ < pb
->x
) {
183 /* FIXME: watch this space for EOL */
184 if( *pix
!= color
|| n
== 255 ) {
185 encode_pixels( ed
, color
, n
);
194 /* this small optimization: (n>63) can save up to two bytes per line
195 * I wonder if this is compatible with all the hardware... */
196 if( color
== 0 && n
> 63 ) {
199 encode_pixels( ed
, color
, n
);
202 if( ed
->nibblewaiting
) {
204 ed
->nibblewaiting
= 0;
210 pixbuf_encode_rle(int x
, int y
, int w
, int h
, char *inbuf
, int stride
,encodedata
*ed
){
218 ed
->nibblewaiting
= 0;
221 for( i
= 0; i
< pb
.y
; i
++ ) {
222 encode_do_row(ed
, &pb
, row
);
226 ed
->oddstart
= ed
->count
;
229 encode_do_control(x
,y
, ed
, &pb
);
234 pixbuf_load_xpm( pixbuf
* pb
, char* xpm
[] ) {
235 int colors
, chrs
, l
, n
;
236 char c
[4], table
[256];
237 unsigned char *b
, *i
;
239 sscanf( xpm
[0], "%d %d %d %d", &pb
->x
, &pb
->y
, &colors
, &chrs
);
241 fprintf( stderr
, "the pixmap MUST be 4 colors or less\n");
245 fprintf( stderr
, "the XPM format MUST be 1 char per pixel\n");
248 if( pb
->x
> 0xFFF || pb
->y
> 0xFFF ) {
249 fprintf( stderr
, "the size is excesive\n");
253 for( l
=0; l
<colors
; l
++ ) {
254 n
= sscanf( xpm
[l
+1], "%c c #%x", &c
[l
], &pb
->rgb
[l
]);
256 /* this one is transparent */
257 pb
->rgb
[l
]=0xff000000;
262 pb
->pixels
= malloc( pb
->x
* pb
->y
);
265 for( l
= colors
+1; l
<= pb
->y
+ colors
; l
++ ) {
274 pixbuf_delete( pixbuf
* pb
) {