comparison spudec.c @ 3166:69ad1e3db38c

Palette support for SPU decoder.
author atmos4
date Tue, 27 Nov 2001 20:16:45 +0000
parents fa8665a91729
children 3538c34117a3
comparison
equal deleted inserted replaced
3165:c9f140f5a34e 3166:69ad1e3db38c
3 Further works: 3 Further works:
4 LGB,... (yeah, try to improve it and insert your name here! ;-) 4 LGB,... (yeah, try to improve it and insert your name here! ;-)
5 5
6 Kim Minh Kaplan 6 Kim Minh Kaplan
7 implement fragments reassembly, RLE decoding. 7 implement fragments reassembly, RLE decoding.
8 image rendering needs to be corrected (see mkcolor & mkalpha). 8 read brightness from the IFO.
9 9
10 For information on SPU format see <URL:http://sam.zoy.org/doc/dvd/subtitles/> 10 For information on SPU format see <URL:http://sam.zoy.org/doc/dvd/subtitles/>
11 11
12 */ 12 */
13 13
15 #include <stdio.h> 15 #include <stdio.h>
16 #include <stdlib.h> 16 #include <stdlib.h>
17 #include "spudec.h" 17 #include "spudec.h"
18 18
19 typedef struct { 19 typedef struct {
20 dvd_priv_t *dvd_info; /* Info from libmpdemux */
20 unsigned char* packet; 21 unsigned char* packet;
21 size_t packet_reserve; /* size of the memory pointed to by packet */ 22 size_t packet_reserve; /* size of the memory pointed to by packet */
22 int packet_offset; /* end of the currently assembled fragment */ 23 int packet_offset; /* end of the currently assembled fragment */
23 int packet_size; /* size of the packet once all fragments are assembled */ 24 int packet_size; /* size of the packet once all fragments are assembled */
24 int control_start; /* index of start of control data */ 25 int control_start; /* index of start of control data */
72 return nib; 73 return nib;
73 } 74 }
74 75
75 static inline int mkalpha(int i) 76 static inline int mkalpha(int i)
76 { 77 {
77 /* for VO 0 is transparent 78 /* In mplayer's alpha planes, 0 is transparent, then 1 is nearly
78 127 is quite dark, but still... 79 opaque upto 255 which is transparent */
79 255 is transparent with color 0, and hum... funny with other colors...
80
81 FIXME, I can't seem to get a good alpha value!
82
83 i is the value read from SPU, from 0 to 15. The function should
84 return the corresponding alpha value suitable for libvo's
85 draw_alpha. */
86 #if 0
87 return (0xf - (i & 0xf)) << 4;
88 #else
89 return (i < 8) ? 127 : 0;
90 #endif
91 }
92
93 static inline int mkcolor(int i)
94 {
95 /* FIXME, have to get the colormap's RGB values from the IFO */
96 #if 0
97 switch (i) { 80 switch (i) {
98 case 15: return 0; 81 case 0xf:
99 default: return i << 4; 82 return 1;
100 } 83 case 0:
101 #else 84 return 0;
102 return i << 4; 85 default:
103 #endif 86 return (0xf - i) << 4;
87 }
104 } 88 }
105 89
106 static void spudec_process_data(spudec_handle_t *this) 90 static void spudec_process_data(spudec_handle_t *this)
107 { 91 {
108 int alpha[4] = { 92 int cmap[4], alpha[4];
109 mkalpha(this->alpha[0]), 93 int i;
110 mkalpha(this->alpha[1]),
111 mkalpha(this->alpha[2]),
112 mkalpha(this->alpha[3])
113 };
114 int cmap[4] = {
115 mkcolor(this->palette[0]),
116 mkcolor(this->palette[1]),
117 mkcolor(this->palette[2]),
118 mkcolor(this->palette[3])
119 };
120 int y = 0, x = 0; 94 int y = 0, x = 0;
95
96 for (i = 0; i < 4; ++i) {
97 alpha[i] = mkalpha(this->alpha[i]);
98 if (alpha[i] == 0)
99 cmap[i] = 0;
100 else {
101 cmap[i] = ((this->dvd_info->vts_file->vts_pgcit->pgci_srp[0].pgc->palette[this->palette[i]] >> 16) & 0xff) - alpha[i];
102 if (cmap[i] < 0)
103 cmap[i] = 0;
104 }
105 }
121 106
122 if (this->image_size < this->width * this->height) { 107 if (this->image_size < this->width * this->height) {
123 if (this->image != NULL) 108 if (this->image != NULL)
124 free(this->image); 109 free(this->image);
125 this->image = malloc(2 * this->width * this->height); 110 this->image = malloc(2 * this->width * this->height);
128 this->aimage = this->image + this->image_size; 113 this->aimage = this->image + this->image_size;
129 } 114 }
130 } 115 }
131 if (this->image == NULL) 116 if (this->image == NULL)
132 return; 117 return;
133 while (this->current_nibble[0] / 2 < this->control_start 118 i = this->current_nibble[1];
119 while (this->current_nibble[0] < i
134 && this->current_nibble[1] / 2 < this->control_start 120 && this->current_nibble[1] / 2 < this->control_start
135 && y < this->height) { 121 && y < this->height) {
136 int len, color; 122 int len, color;
137 unsigned int rle = 0; 123 unsigned int rle = 0;
138 rle = get_nibble(this); 124 rle = get_nibble(this);
145 if (rle < 0x0004) 131 if (rle < 0x0004)
146 rle |= ((this->width - x) << 2); 132 rle |= ((this->width - x) << 2);
147 } 133 }
148 } 134 }
149 } 135 }
150 color = rle & 0x3; 136 color = 3 - (rle & 0x3);
151 len = rle >> 2; 137 len = rle >> 2;
152 if (len > this->width - x) 138 if (len > this->width - x)
153 len = this->width - x; 139 len = this->width - x;
154 /* FIXME have to use palette and alpha map*/ 140 /* FIXME have to use palette and alpha map*/
155 memset(this->image + y * this->width + x, cmap[color], len); 141 memset(this->image + y * this->width + x, cmap[color], len);
156 if (alpha[color] < cmap[color]) { 142 memset(this->aimage + y * this->width + x, alpha[color], len);
157 memset(this->aimage + y * this->width + x, 1, len);
158 } else {
159 memset(this->aimage + y * this->width + x, alpha[color] - cmap[color], len);
160 }
161 x += len; 143 x += len;
162 if (x >= this->width) { 144 if (x >= this->width) {
163 next_line(this); 145 next_line(this);
164 x = 0; 146 x = 0;
165 ++y; 147 ++y;
227 this->start_col = a >> 12; 209 this->start_col = a >> 12;
228 this->end_col = a & 0xfff; 210 this->end_col = a & 0xfff;
229 this->width = this->end_col - this->start_col + 1; 211 this->width = this->end_col - this->start_col + 1;
230 this->start_row = b >> 12; 212 this->start_row = b >> 12;
231 this->end_row = b & 0xfff; 213 this->end_row = b & 0xfff;
232 this->height = this->end_row - this->start_row + 1; 214 this->height = this->end_row - this->start_row /* + 1 */;
233 printf("Coords col: %d - %d row: %d - %d (%dx%d)\n", 215 printf("Coords col: %d - %d row: %d - %d (%dx%d)\n",
234 this->start_col, this->end_col, this->start_row, this->end_row, 216 this->start_col, this->end_col, this->start_row, this->end_row,
235 this->width, this->height); 217 this->width, this->height);
236 off+=6; 218 off+=6;
237 break; 219 break;
311 if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image) 293 if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image)
312 draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height, 294 draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
313 spu->image, spu->aimage, spu->width); 295 spu->image, spu->aimage, spu->width);
314 } 296 }
315 297
316 void *spudec_new() 298 void *spudec_new(dvd_priv_t *dvd_info)
317 { 299 {
318 spudec_handle_t *this = calloc(1, sizeof(spudec_handle_t)); 300 spudec_handle_t *this = calloc(1, sizeof(spudec_handle_t));
319 if (this) { 301 if (this) {
320 ; 302 this->dvd_info = dvd_info;
321 } 303 }
322 else 304 else
323 perror("FATAL: spudec_init: calloc"); 305 perror("FATAL: spudec_init: calloc");
324 return this; 306 return this;
325 } 307 }