Mercurial > mplayer.hg
comparison sub/spuenc.c @ 32470:139876e79725
Move spuenc.[ch] from libvo to sub.
author | cigaes |
---|---|
date | Wed, 27 Oct 2010 17:55:45 +0000 |
parents | libvo/spuenc.c@84d86f175613 |
children |
comparison
equal
deleted
inserted
replaced
32469:3fef2e17a03f | 32470:139876e79725 |
---|---|
1 /* | |
2 * encode a pixmap with RLE | |
3 * | |
4 * Copyright (C) 2000 Alejandro J. Cura <alecu@protocultura.net> | |
5 * | |
6 * (modified a bit to work with the dxr3 driver...4/2/2002 cg) | |
7 * | |
8 * Based on the hard work of: | |
9 * | |
10 * Samuel Hocevar <sam@via.ecp.fr> and Michel Lespinasse <walken@via.ecp.fr> | |
11 * | |
12 * This file is part of MPlayer. | |
13 * | |
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. | |
18 * | |
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. | |
23 * | |
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. | |
27 */ | |
28 | |
29 #include <stdio.h> | |
30 #include <stdlib.h> | |
31 #include "unistd.h" | |
32 #include "spuenc.h" | |
33 | |
34 typedef struct { | |
35 int x, y; | |
36 unsigned int rgb[4]; | |
37 unsigned char* pixels; | |
38 } pixbuf; | |
39 | |
40 static void | |
41 encode_do_control(int x,int y, encodedata* ed, pixbuf* pb) { | |
42 int controlstart= ed->count; | |
43 int x1; | |
44 int i; | |
45 unsigned int top, left, bottom, right; | |
46 | |
47 top= 450 - pb->y/2; | |
48 left=(720 / 2) - (pb->x / 2); | |
49 top= 32;//this forces the first bit to be visible on a TV | |
50 left= 32;//you could actually pass in x/y and do some nice | |
51 //calculations for making it look right... | |
52 bottom= top + pb->y - 1; | |
53 right= left + pb->x - 1; | |
54 | |
55 /* the format of this is well described by a page: | |
56 * http://members.aol.com/mpucoder/DVD/spu.html | |
57 * | |
58 * note I changed the layout of commands to turn off the subpic as the | |
59 * first command, and then turn on the new subpic...this is so we can | |
60 * leave the subpic on for an arbitrary ammount of time as controlled by | |
61 * mplayer (ie when we turn on the subpic we don't know how long it should | |
62 * stay on when using mplayer). | |
63 * with this layout we turn off the last subpic as we are turning on the | |
64 * new one. | |
65 * The original hd it turn on the subpic, and delay the turn off command using | |
66 * the durration/delay feature. | |
67 * */ | |
68 /* start at x0+2*/ | |
69 i= controlstart; | |
70 /* display duration... */ | |
71 // ed->data[i++]= 0x00; | |
72 // ed->data[i++]= 0x00; //durration before turn off command occurs | |
73 //in 90000/1024 units | |
74 | |
75 /* x1 */ | |
76 // x1=i+4; | |
77 // ed->data[i++]= x1 >> 8;//location of next command block | |
78 // ed->data[i++]= x1 & 0xff; | |
79 /* finish it */ | |
80 // ed->data[i++]= 0x02;//turn off command | |
81 // ed->data[i++]= 0xff;//end of command block | |
82 x1= i; //marker for last command block address | |
83 | |
84 /* display duration... */ | |
85 ed->data[i++]= 0x00; | |
86 ed->data[i++]= 0x00; //durration before turn on command occurs | |
87 //in 90000/1024 units | |
88 /* x1 */ | |
89 ed->data[i++]= x1 >> 8; //since this is the last command block, this | |
90 ed->data[i++]= x1 & 0xff;//points back to itself | |
91 | |
92 | |
93 /* 0x01: start displaying */ | |
94 ed->data[i++]= 0x01; | |
95 | |
96 /* 0x03: palette info */ | |
97 ed->data[i++]= 0x03; | |
98 ed->data[i++]= 0x08; | |
99 ed->data[i++]= 0x7f; | |
100 /* | |
101 * The palette is a coded index (one of 16) 0 is black, 0xf is white | |
102 * (unless you screw with the default palette) | |
103 * for what I am doing I only use white. | |
104 * 7 is lt grey, and 8 is dk grey... | |
105 * */ | |
106 /* 0x04: transparency info (reversed) */ | |
107 ed->data[i++]= 0x04; | |
108 ed->data[i++]= 0xFF;//change the opacity values of the color entries | |
109 ed->data[i++]= 0xF0;//say if you wanted white text on a black backround | |
110 //note you will have to work harder, by finding the | |
111 //bounding box of the text, and use a non transparent black palette | |
112 // entry to fill the backround with, (say color 1 instead of 0) | |
113 | |
114 /* 0x05: coordinates */ | |
115 ed->data[i++]= 0x05; | |
116 ed->data[i++]= left >> 4; | |
117 ed->data[i++]= ((left&0xf)<<4)+(right>>8); | |
118 ed->data[i++]= (right&0xff); | |
119 ed->data[i++]= top >> 4; | |
120 ed->data[i++]= ((top&0xf)<<4)+(bottom>>8); | |
121 ed->data[i++]= (bottom&0xff); | |
122 | |
123 /* 0x06: both fields' offsets */ | |
124 ed->data[i++]= 0x06; | |
125 ed->data[i++]= 0x00; | |
126 ed->data[i++]= 0x04; | |
127 ed->data[i++]= ed->oddstart >> 8; | |
128 ed->data[i++]= ed->oddstart & 0xff; | |
129 | |
130 /* 0xFF: end sequence */ | |
131 ed->data[i++]= 0xFF; | |
132 if(! i&1 ) { | |
133 ed->data[i++]= 0xff; | |
134 } | |
135 | |
136 /* x0 */ | |
137 ed->data[2]= (controlstart) >> 8; | |
138 ed->data[3]= (controlstart) & 0xff; | |
139 | |
140 /* packet size */ | |
141 ed->data[0]= i >> 8; | |
142 ed->data[1]= i & 0xff; | |
143 | |
144 ed->count= i; | |
145 } | |
146 | |
147 static void | |
148 encode_put_nibble( encodedata* ed, unsigned char nibble ) { | |
149 if( ed->nibblewaiting ) { | |
150 ed->data[ed->count++]|= nibble; | |
151 ed->nibblewaiting= 0; | |
152 } else { | |
153 ed->data[ed->count]= nibble<<4; | |
154 ed->nibblewaiting= 1; | |
155 } | |
156 } | |
157 | |
158 static void | |
159 encode_pixels( encodedata* ed, int color, int number ) { | |
160 if(number > 3) { | |
161 if(number > 15) { | |
162 encode_put_nibble( ed, 0 ); | |
163 if(number > 63) { | |
164 encode_put_nibble( ed, (number & 0xC0)>>6 ); | |
165 } | |
166 } | |
167 encode_put_nibble( ed, (number & 0x3C)>>2 ); | |
168 } | |
169 encode_put_nibble( ed, ((number & 0xF)<<2) | color); | |
170 } | |
171 | |
172 static void | |
173 encode_eol( encodedata* ed ) { | |
174 if( ed->nibblewaiting ) { | |
175 ed->count++; | |
176 ed->nibblewaiting= 0; | |
177 } | |
178 ed->data[ed->count++]= 0x00; | |
179 ed->data[ed->count++]= 0x00; | |
180 } | |
181 | |
182 static void | |
183 encode_do_row( encodedata* ed, pixbuf* pb, int row ) { | |
184 int i= 0; | |
185 unsigned char* pix= pb->pixels + row * pb->x; | |
186 int color= *pix; | |
187 int n= 0; /* the number of pixels of this color */ | |
188 | |
189 while( i++ < pb->x ) { | |
190 /* FIXME: watch this space for EOL */ | |
191 if( *pix != color || n == 255 ) { | |
192 encode_pixels( ed, color, n ); | |
193 color= *pix; | |
194 n= 1; | |
195 } else { | |
196 n++; | |
197 } | |
198 pix++; | |
199 } | |
200 | |
201 /* this small optimization: (n>63) can save up to two bytes per line | |
202 * I wonder if this is compatible with all the hardware... */ | |
203 if( color == 0 && n > 63 ) { | |
204 encode_eol( ed ); | |
205 } else { | |
206 encode_pixels( ed, color, n ); | |
207 } | |
208 | |
209 if( ed->nibblewaiting ) { | |
210 ed->count++; | |
211 ed->nibblewaiting= 0; | |
212 } | |
213 } | |
214 | |
215 | |
216 void | |
217 pixbuf_encode_rle(int x, int y, int w, int h, char *inbuf, int stride,encodedata *ed){ | |
218 pixbuf pb; | |
219 int i, row; | |
220 pb.x = w; | |
221 pb.y = h; | |
222 | |
223 pb.pixels = inbuf; | |
224 ed->count= 4; | |
225 ed->nibblewaiting= 0; | |
226 | |
227 row= 0; | |
228 for( i= 0; i < pb.y; i++ ) { | |
229 encode_do_row(ed, &pb, row); | |
230 row+= 2; | |
231 if( row > pb.y ) { | |
232 row= 1; | |
233 ed->oddstart= ed->count; | |
234 } | |
235 } | |
236 encode_do_control(x,y, ed, &pb); | |
237 } |