~medibuntu-maintainers/mplayer/medibuntu.lucid

1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1
/* SPUdec.c
2
   Skeleton of function spudec_process_controll() is from xine sources.
3
   Further works:
4
   LGB,... (yeah, try to improve it and insert your name here! ;-)
5
6
   Kim Minh Kaplan
7
   implement fragments reassembly, RLE decoding.
8
   read brightness from the IFO.
9
10
   For information on SPU format see <URL:http://sam.zoy.org/doc/dvd/subtitles/>
11
   and <URL:http://members.aol.com/mpucoder/DVD/spu.html>
12
13
 */
14
#include "config.h"
15
#include "mp_msg.h"
16
17
#include <errno.h>
18
#include <limits.h>
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <unistd.h>
22
#include <string.h>
23
#include <math.h>
24
#include "libvo/video_out.h"
25
#include "spudec.h"
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
26
#include "vobsub.h"
27
#include "libavutil/avutil.h"
28
#include "libavutil/intreadwrite.h"
1.1.3 by William Grant
Import upstream version 1.0~rc1
29
#include "libswscale/swscale.h"
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
30
31
/* Valid values for spu_aamode:
32
   0: none (fastest, most ugly)
33
   1: approximate
34
   2: full (slowest)
35
   3: bilinear (similiar to vobsub, fast and not too bad)
36
   4: uses swscaler gaussian (this is the only one that looks good)
37
 */
38
39
int spu_aamode = 3;
40
int spu_alignment = -1;
41
float spu_gaussvar = 1.0;
42
extern int sub_pos;
43
44
typedef struct packet_t packet_t;
45
struct packet_t {
46
  unsigned char *packet;
47
  unsigned int palette[4];
48
  unsigned int alpha[4];
49
  unsigned int control_start;	/* index of start of control data */
50
  unsigned int current_nibble[2]; /* next data nibble (4 bits) to be
51
                                     processed (for RLE decoding) for
52
                                     even and odd lines */
53
  int deinterlace_oddness;	/* 0 or 1, index into current_nibble */
54
  unsigned int start_col, end_col;
55
  unsigned int start_row, end_row;
56
  unsigned int width, height, stride;
57
  unsigned int start_pts, end_pts;
58
  packet_t *next;
59
};
60
61
typedef struct {
62
  packet_t *queue_head;
63
  packet_t *queue_tail;
64
  unsigned int global_palette[16];
65
  unsigned int orig_frame_width, orig_frame_height;
66
  unsigned char* packet;
67
  size_t packet_reserve;	/* size of the memory pointed to by packet */
68
  unsigned int packet_offset;	/* end of the currently assembled fragment */
69
  unsigned int packet_size;	/* size of the packet once all fragments are assembled */
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
70
  int packet_pts;		/* PTS for this packet */
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
71
  unsigned int palette[4];
72
  unsigned int alpha[4];
73
  unsigned int cuspal[4];
74
  unsigned int custom;
75
  unsigned int now_pts;
76
  unsigned int start_pts, end_pts;
77
  unsigned int start_col, end_col;
78
  unsigned int start_row, end_row;
79
  unsigned int width, height, stride;
80
  size_t image_size;		/* Size of the image buffer */
81
  unsigned char *image;		/* Grayscale value */
82
  unsigned char *aimage;	/* Alpha value */
83
  unsigned int scaled_frame_width, scaled_frame_height;
84
  unsigned int scaled_start_col, scaled_start_row;
85
  unsigned int scaled_width, scaled_height, scaled_stride;
86
  size_t scaled_image_size;
87
  unsigned char *scaled_image;
88
  unsigned char *scaled_aimage;
89
  int auto_palette; /* 1 if we lack a palette and must use an heuristic. */
90
  int font_start_level;  /* Darkest value used for the computed font */
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
91
  const vo_functions_t *hw_spu;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
92
  int spu_changed;
93
  unsigned int forced_subs_only;     /* flag: 0=display all subtitle, !0 display only forced subtitles */
94
  unsigned int is_forced_sub;         /* true if current subtitle is a forced subtitle */
95
} spudec_handle_t;
96
97
static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
98
{
99
  if (this->queue_head == NULL)
100
    this->queue_head = packet;
101
  else
102
    this->queue_tail->next = packet;
103
  this->queue_tail = packet;
104
}
105
106
static packet_t *spudec_dequeue_packet(spudec_handle_t *this)
107
{
108
  packet_t *retval = this->queue_head;
109
110
  this->queue_head = retval->next;
111
  if (this->queue_head == NULL)
112
    this->queue_tail = NULL;
113
114
  return retval;
115
}
116
117
static void spudec_free_packet(packet_t *packet)
118
{
119
  if (packet->packet != NULL)
120
    free(packet->packet);
121
  free(packet);
122
}
123
124
static inline unsigned int get_be16(const unsigned char *p)
125
{
126
  return (p[0] << 8) + p[1];
127
}
128
129
static inline unsigned int get_be24(const unsigned char *p)
130
{
131
  return (get_be16(p) << 8) + p[2];
132
}
133
134
static void next_line(packet_t *packet)
135
{
136
  if (packet->current_nibble[packet->deinterlace_oddness] % 2)
137
    packet->current_nibble[packet->deinterlace_oddness]++;
138
  packet->deinterlace_oddness = (packet->deinterlace_oddness + 1) % 2;
139
}
140
141
static inline unsigned char get_nibble(packet_t *packet)
142
{
143
  unsigned char nib;
144
  unsigned int *nibblep = packet->current_nibble + packet->deinterlace_oddness;
145
  if (*nibblep / 2 >= packet->control_start) {
146
    mp_msg(MSGT_SPUDEC,MSGL_WARN, "SPUdec: ERROR: get_nibble past end of packet\n");
147
    return 0;
148
  }
149
  nib = packet->packet[*nibblep / 2];
150
  if (*nibblep % 2)
151
    nib &= 0xf;
152
  else
153
    nib >>= 4;
154
  ++*nibblep;
155
  return nib;
156
}
157
158
static inline int mkalpha(int i)
159
{
160
  /* In mplayer's alpha planes, 0 is transparent, then 1 is nearly
161
     opaque upto 255 which is transparent */
162
  switch (i) {
163
  case 0xf:
164
    return 1;
165
  case 0:
166
    return 0;
167
  default:
168
    return (0xf - i) << 4;
169
  }
170
}
171
172
/* Cut the sub to visible part */
173
static inline void spudec_cut_image(spudec_handle_t *this)
174
{
175
  unsigned int fy, ly;
176
  unsigned int first_y, last_y;
177
  unsigned char *image;
178
  unsigned char *aimage;
179
180
  if (this->stride == 0 || this->height == 0) {
181
    return;
182
  }
183
184
  for (fy = 0; fy < this->image_size && !this->aimage[fy]; fy++);
185
  for (ly = this->stride * this->height-1; ly && !this->aimage[ly]; ly--);
186
  first_y = fy / this->stride;
187
  last_y = ly / this->stride;
188
  //printf("first_y: %d, last_y: %d\n", first_y, last_y);
189
  this->start_row += first_y;
190
191
  // Some subtitles trigger this condition
192
  if (last_y + 1 > first_y ) {
193
	  this->height = last_y - first_y +1;
194
  } else {
195
	  this->height = 0;
196
	  this->image_size = 0;
197
	  return;
198
  }
199
  
200
//  printf("new h %d new start %d (sz %d st %d)---\n\n", this->height, this->start_row, this->image_size, this->stride);
201
202
  image = malloc(2 * this->stride * this->height);
203
  if(image){
204
    this->image_size = this->stride * this->height;
205
    aimage = image + this->image_size;
206
    memcpy(image, this->image + this->stride * first_y, this->image_size);
207
    memcpy(aimage, this->aimage + this->stride * first_y, this->image_size);
208
    free(this->image);
209
    this->image = image;
210
    this->aimage = aimage;
211
  } else {
212
    mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: update_spu: malloc requested %d bytes\n", 2 * this->stride * this->height);
213
  }
214
}
215
216
static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
217
{
218
  unsigned int cmap[4], alpha[4];
219
  unsigned int i, x, y;
220
221
  this->scaled_frame_width = 0;
222
  this->scaled_frame_height = 0;
223
  this->start_col = packet->start_col;
224
  this->end_col = packet->end_col;
225
  this->start_row = packet->start_row;
226
  this->end_row = packet->end_row;
227
  this->height = packet->height;
228
  this->width = packet->width;
229
  this->stride = packet->stride;
230
  for (i = 0; i < 4; ++i) {
231
    alpha[i] = mkalpha(packet->alpha[i]);
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
232
    if (this->custom && (this->cuspal[i] >> 31) != 0)
233
      alpha[i] = 0;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
234
    if (alpha[i] == 0)
235
      cmap[i] = 0;
236
    else if (this->custom){
237
      cmap[i] = ((this->cuspal[i] >> 16) & 0xff);
238
      if (cmap[i] + alpha[i] > 255)
239
	cmap[i] = 256 - alpha[i];
240
    }
241
    else {
242
      cmap[i] = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);
243
      if (cmap[i] + alpha[i] > 255)
244
	cmap[i] = 256 - alpha[i];
245
    }
246
  }
247
248
  if (this->image_size < this->stride * this->height) {
249
    if (this->image != NULL) {
250
      free(this->image);
251
      this->image_size = 0;
252
    }
253
    this->image = malloc(2 * this->stride * this->height);
254
    if (this->image) {
255
      this->image_size = this->stride * this->height;
256
      this->aimage = this->image + this->image_size;
257
    }
258
  }
259
  if (this->image == NULL)
260
    return;
261
262
  /* Kludge: draw_alpha needs width multiple of 8. */
263
  if (this->width < this->stride)
264
    for (y = 0; y < this->height; ++y) {
265
      memset(this->aimage + y * this->stride + this->width, 0, this->stride - this->width);
266
      /* FIXME: Why is this one needed? */
267
      memset(this->image + y * this->stride + this->width, 0, this->stride - this->width);
268
    }
269
270
  i = packet->current_nibble[1];
271
  x = 0;
272
  y = 0;
273
  while (packet->current_nibble[0] < i
274
	 && packet->current_nibble[1] / 2 < packet->control_start
275
	 && y < this->height) {
276
    unsigned int len, color;
277
    unsigned int rle = 0;
278
    rle = get_nibble(packet);
279
    if (rle < 0x04) {
280
      rle = (rle << 4) | get_nibble(packet);
281
      if (rle < 0x10) {
282
	rle = (rle << 4) | get_nibble(packet);
283
	if (rle < 0x040) {
284
	  rle = (rle << 4) | get_nibble(packet);
285
	  if (rle < 0x0004)
286
	    rle |= ((this->width - x) << 2);
287
	}
288
      }
289
    }
290
    color = 3 - (rle & 0x3);
291
    len = rle >> 2;
292
    if (len > this->width - x || len == 0)
293
      len = this->width - x;
294
    /* FIXME have to use palette and alpha map*/
295
    memset(this->image + y * this->stride + x, cmap[color], len);
296
    memset(this->aimage + y * this->stride + x, alpha[color], len);
297
    x += len;
298
    if (x >= this->width) {
299
      next_line(packet);
300
      x = 0;
301
      ++y;
302
    }
303
  }
304
  spudec_cut_image(this);
305
}
306
307
308
/*
309
  This function tries to create a usable palette.
310
  It determines how many non-transparent colors are used, and assigns different
311
gray scale values to each color.
312
  I tested it with four streams and even got something readable. Half of the
313
times I got black characters with white around and half the reverse.
314
*/
315
static void compute_palette(spudec_handle_t *this, packet_t *packet)
316
{
317
  int used[16],i,cused,start,step,color;
318
319
  memset(used, 0, sizeof(used));
320
  for (i=0; i<4; i++)
321
    if (packet->alpha[i]) /* !Transparent? */
322
       used[packet->palette[i]] = 1;
323
  for (cused=0, i=0; i<16; i++)
324
    if (used[i]) cused++;
325
  if (!cused) return;
326
  if (cused == 1) {
327
    start = 0x80;
328
    step = 0;
329
  } else {
330
    start = this->font_start_level;
331
    step = (0xF0-this->font_start_level)/(cused-1);
332
  }
333
  memset(used, 0, sizeof(used));
334
  for (i=0; i<4; i++) {
335
    color = packet->palette[i];
336
    if (packet->alpha[i] && !used[color]) { /* not assigned? */
337
       used[color] = 1;
338
       this->global_palette[color] = start<<16;
339
       start += step;
340
    }
341
  }
342
}
343
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
344
static void spudec_process_control(spudec_handle_t *this, int pts100)
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
345
{
346
  int a,b; /* Temporary vars */
347
  unsigned int date, type;
348
  unsigned int off;
349
  unsigned int start_off = 0;
350
  unsigned int next_off;
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
351
  unsigned int start_pts = 0;
352
  unsigned int end_pts = 0;
353
  unsigned int current_nibble[2] = {0, 0};
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
354
  unsigned int control_start;
355
  unsigned int display = 0;
356
  unsigned int start_col = 0;
357
  unsigned int end_col = 0;
358
  unsigned int start_row = 0;
359
  unsigned int end_row = 0;
360
  unsigned int width = 0;
361
  unsigned int height = 0;
362
  unsigned int stride = 0;
363
364
  control_start = get_be16(this->packet + 2);
365
  next_off = control_start;
366
  while (start_off != next_off) {
367
    start_off = next_off;
368
    date = get_be16(this->packet + start_off) * 1024;
369
    next_off = get_be16(this->packet + start_off + 2);
370
    mp_msg(MSGT_SPUDEC,MSGL_DBG2, "date=%d\n", date);
371
    off = start_off + 4;
372
    for (type = this->packet[off++]; type != 0xff; type = this->packet[off++]) {
373
      mp_msg(MSGT_SPUDEC,MSGL_DBG2, "cmd=%d  ",type);
374
      switch(type) {
375
      case 0x00:
376
	/* Menu ID, 1 byte */
377
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Menu ID\n");
378
        /* shouldn't a Menu ID type force display start? */
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
379
	start_pts = pts100 < 0 && -pts100 >= date ? 0 : pts100 + date;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
380
	end_pts = UINT_MAX;
381
	display = 1;
382
	this->is_forced_sub=~0; // current subtitle is forced
383
	break;
384
      case 0x01:
385
	/* Start display */
386
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Start display!\n");
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
387
	start_pts = pts100 < 0 && -pts100 >= date ? 0 : pts100 + date;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
388
	end_pts = UINT_MAX;
389
	display = 1;
390
	this->is_forced_sub=0;
391
	break;
392
      case 0x02:
393
	/* Stop display */
394
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Stop display!\n");
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
395
	end_pts = pts100 < 0 && -pts100 >= date ? 0 : pts100 + date;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
396
	break;
397
      case 0x03:
398
	/* Palette */
399
	this->palette[0] = this->packet[off] >> 4;
400
	this->palette[1] = this->packet[off] & 0xf;
401
	this->palette[2] = this->packet[off + 1] >> 4;
402
	this->palette[3] = this->packet[off + 1] & 0xf;
403
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Palette %d, %d, %d, %d\n",
404
	       this->palette[0], this->palette[1], this->palette[2], this->palette[3]);
405
	off+=2;
406
	break;
407
      case 0x04:
408
	/* Alpha */
409
	this->alpha[0] = this->packet[off] >> 4;
410
	this->alpha[1] = this->packet[off] & 0xf;
411
	this->alpha[2] = this->packet[off + 1] >> 4;
412
	this->alpha[3] = this->packet[off + 1] & 0xf;
413
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Alpha %d, %d, %d, %d\n",
414
	       this->alpha[0], this->alpha[1], this->alpha[2], this->alpha[3]);
415
	off+=2;
416
	break;
417
      case 0x05:
418
	/* Co-ords */
419
	a = get_be24(this->packet + off);
420
	b = get_be24(this->packet + off + 3);
421
	start_col = a >> 12;
422
	end_col = a & 0xfff;
423
	width = (end_col < start_col) ? 0 : end_col - start_col + 1;
424
	stride = (width + 7) & ~7; /* Kludge: draw_alpha needs width multiple of 8 */
425
	start_row = b >> 12;
426
	end_row = b & 0xfff;
427
	height = (end_row < start_row) ? 0 : end_row - start_row /* + 1 */;
428
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Coords  col: %d - %d  row: %d - %d  (%dx%d)\n",
429
	       start_col, end_col, start_row, end_row,
430
	       width, height);
431
	off+=6;
432
	break;
433
      case 0x06:
434
	/* Graphic lines */
435
	current_nibble[0] = 2 * get_be16(this->packet + off);
436
	current_nibble[1] = 2 * get_be16(this->packet + off + 2);
437
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Graphic offset 1: %d  offset 2: %d\n",
438
	       current_nibble[0] / 2, current_nibble[1] / 2);
439
	off+=4;
440
	break;
441
      case 0xff:
442
	/* All done, bye-bye */
443
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Done!\n");
444
	return;
445
//	break;
446
      default:
447
	mp_msg(MSGT_SPUDEC,MSGL_WARN,"spudec: Error determining control type 0x%02x.  Skipping %d bytes.\n",
448
	       type, next_off - off);
449
	goto next_control;
450
      }
451
    }
452
  next_control:
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
453
    if (!display)
454
      continue;
455
    if (end_pts == UINT_MAX && start_off != next_off) {
456
      end_pts = get_be16(this->packet + next_off) * 1024;
457
      end_pts = 1 - pts100 >= end_pts ? 0 : pts100 + end_pts - 1;
458
    }
459
    if (end_pts > 0) {
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
460
      packet_t *packet = calloc(1, sizeof(packet_t));
461
      int i;
462
      packet->start_pts = start_pts;
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
463
      packet->end_pts = end_pts;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
464
      packet->current_nibble[0] = current_nibble[0];
465
      packet->current_nibble[1] = current_nibble[1];
466
      packet->start_row = start_row;
467
      packet->end_row = end_row;
468
      packet->start_col = start_col;
469
      packet->end_col = end_col;
470
      packet->width = width;
471
      packet->height = height;
472
      packet->stride = stride;
473
      packet->control_start = control_start;
474
      for (i=0; i<4; i++) {
475
	packet->alpha[i] = this->alpha[i];
476
	packet->palette[i] = this->palette[i];
477
      }
478
      packet->packet = malloc(this->packet_size);
479
      memcpy(packet->packet, this->packet, this->packet_size);
480
      spudec_queue_packet(this, packet);
481
    }
482
  }
483
}
484
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
485
static void spudec_decode(spudec_handle_t *this, int pts100)
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
486
{
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
487
  if (!this->hw_spu)
488
    spudec_process_control(this, pts100);
489
  else if (pts100 >= 0) {
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
490
    static vo_mpegpes_t packet = { NULL, 0, 0x20, 0 };
491
    static vo_mpegpes_t *pkg=&packet;
492
    packet.data = this->packet;
493
    packet.size = this->packet_size;
494
    packet.timestamp = pts100;
495
    this->hw_spu->draw_frame((uint8_t**)&pkg);
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
496
  }
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
497
}
498
499
int spudec_changed(void * this)
500
{
501
    spudec_handle_t * spu = (spudec_handle_t*)this;
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
502
    return spu->spu_changed || spu->now_pts > spu->end_pts;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
503
}
504
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
505
void spudec_assemble(void *this, unsigned char *packet, unsigned int len, int pts100)
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
506
{
507
  spudec_handle_t *spu = (spudec_handle_t*)this;
508
//  spudec_heartbeat(this, pts100);
509
  if (len < 2) {
510
      mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUasm: packet too short\n");
511
      return;
512
  }
513
#if 0
514
  if ((spu->packet_pts + 10000) < pts100) {
515
    // [cb] too long since last fragment: force new packet
516
    spu->packet_offset = 0;
517
  }
518
#endif
519
  spu->packet_pts = pts100;
520
  if (spu->packet_offset == 0) {
521
    unsigned int len2 = get_be16(packet);
522
    // Start new fragment
523
    if (spu->packet_reserve < len2) {
524
      if (spu->packet != NULL)
525
	free(spu->packet);
526
      spu->packet = malloc(len2);
527
      spu->packet_reserve = spu->packet != NULL ? len2 : 0;
528
    }
529
    if (spu->packet != NULL) {
530
      spu->packet_size = len2;
531
      if (len > len2) {
532
	mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUasm: invalid frag len / len2: %d / %d \n", len, len2);
533
	return;
534
      }
535
      memcpy(spu->packet, packet, len);
536
      spu->packet_offset = len;
537
      spu->packet_pts = pts100;
538
    }
539
  } else {
540
    // Continue current fragment
541
    if (spu->packet_size < spu->packet_offset + len){
542
      mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUasm: invalid fragment\n");
543
      spu->packet_size = spu->packet_offset = 0;
544
      return;
545
    } else {
546
      memcpy(spu->packet + spu->packet_offset, packet, len);
547
      spu->packet_offset += len;
548
    }
549
  }
550
#if 1
551
  // check if we have a complete packet (unfortunatelly packet_size is bad
552
  // for some disks)
553
  // [cb] packet_size is padded to be even -> may be one byte too long
554
  if ((spu->packet_offset == spu->packet_size) ||
555
      ((spu->packet_offset + 1) == spu->packet_size)){
556
    unsigned int x=0,y;
557
    while(x+4<=spu->packet_offset){
558
      y=get_be16(spu->packet+x+2); // next control pointer
559
      mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPUtest: x=%d y=%d off=%d size=%d\n",x,y,spu->packet_offset,spu->packet_size);
560
      if(x>=4 && x==y){		// if it points to self - we're done!
561
        // we got it!
562
	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPUgot: off=%d  size=%d \n",spu->packet_offset,spu->packet_size);
563
	spudec_decode(spu, pts100);
564
	spu->packet_offset = 0;
565
	break;
566
      }
567
      if(y<=x || y>=spu->packet_size){ // invalid?
568
	mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUtest: broken packet!!!!! y=%d < x=%d\n",y,x);
569
        spu->packet_size = spu->packet_offset = 0;
570
        break;
571
      }
572
      x=y;
573
    }
574
    // [cb] packet is done; start new packet
575
    spu->packet_offset = 0;
576
  }
577
#else
578
  if (spu->packet_offset == spu->packet_size) {
579
    spudec_decode(spu, pts100);
580
    spu->packet_offset = 0;
581
  }
582
#endif
583
}
584
585
void spudec_reset(void *this)	// called after seek
586
{
587
  spudec_handle_t *spu = (spudec_handle_t*)this;
588
  while (spu->queue_head)
589
    spudec_free_packet(spudec_dequeue_packet(spu));
590
  spu->now_pts = 0;
591
  spu->end_pts = 0;
592
  spu->packet_size = spu->packet_offset = 0;
593
}
594
595
void spudec_heartbeat(void *this, unsigned int pts100)
596
{ 
597
  spudec_handle_t *spu = (spudec_handle_t*) this;
598
  spu->now_pts = pts100;
599
600
  while (spu->queue_head != NULL && pts100 >= spu->queue_head->start_pts) {
601
    packet_t *packet = spudec_dequeue_packet(spu);
602
    spu->start_pts = packet->start_pts;
603
    spu->end_pts = packet->end_pts;
604
    if (spu->auto_palette)
605
      compute_palette(spu, packet);
606
    spudec_process_data(spu, packet);
607
    spudec_free_packet(packet);
608
    spu->spu_changed = 1;
609
  }
610
}
611
612
int spudec_visible(void *this){
613
    spudec_handle_t *spu = (spudec_handle_t *)this;
614
    int ret=(spu->start_pts <= spu->now_pts &&
615
	     spu->now_pts < spu->end_pts &&
616
	     spu->height > 0);
617
//    printf("spu visible: %d  \n",ret);
618
    return ret;
619
}
620
621
void spudec_set_forced_subs_only(void * const this, const unsigned int flag)
622
{
623
  if(this){
624
      ((spudec_handle_t *)this)->forced_subs_only=flag;
625
      mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPU: Display only forced subs now %s\n", flag ? "enabled": "disabled");
626
  }
627
}
628
629
void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
630
{
631
    spudec_handle_t *spu = (spudec_handle_t *)this;
632
    if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image)
633
    {
634
	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
635
		   spu->image, spu->aimage, spu->stride);
636
	spu->spu_changed = 0;
637
    }
638
}
639
640
/* calc the bbox for spudec subs */
641
void spudec_calc_bbox(void *me, unsigned int dxs, unsigned int dys, unsigned int* bbox)
642
{
643
  spudec_handle_t *spu;
644
  spu = (spudec_handle_t *)me;
645
  if (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
646
  || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys)) {
647
    bbox[0] = spu->start_col;
648
    bbox[1] = spu->start_col + spu->width;
649
    bbox[2] = spu->start_row;
650
    bbox[3] = spu->start_row + spu->height;
651
  }
652
  else if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {
653
    unsigned int scalex = 0x100 * dxs / spu->orig_frame_width;
654
    unsigned int scaley = 0x100 * dys / spu->orig_frame_height;
655
    bbox[0] = spu->start_col * scalex / 0x100;
656
    bbox[1] = spu->start_col * scalex / 0x100 + spu->width * scalex / 0x100;
657
    switch (spu_alignment) {
658
    case 0:
659
      bbox[3] = dys*sub_pos/100 + spu->height * scaley / 0x100;
660
      if (bbox[3] > dys) bbox[3] = dys;
661
      bbox[2] = bbox[3] - spu->height * scaley / 0x100;
662
      break;
663
    case 1:
664
      if (sub_pos < 50) {
665
        bbox[2] = dys*sub_pos/100 - spu->height * scaley / 0x200;
666
        bbox[3] = bbox[2] + spu->height;
667
      } else {
668
        bbox[3] = dys*sub_pos/100 + spu->height * scaley / 0x200;
669
        if (bbox[3] > dys) bbox[3] = dys;
670
        bbox[2] = bbox[3] - spu->height * scaley / 0x100;
671
      }
672
      break;
673
    case 2:
674
      bbox[2] = dys*sub_pos/100 - spu->height * scaley / 0x100;
675
      bbox[3] = bbox[2] + spu->height;
676
      break;
677
    default: /* -1 */
678
      bbox[2] = spu->start_row * scaley / 0x100;
679
      bbox[3] = spu->start_row * scaley / 0x100 + spu->height * scaley / 0x100;
680
      break;
681
    }
682
  }
683
}
684
/* transform mplayer's alpha value into an opacity value that is linear */
685
static inline int canon_alpha(int alpha)
686
{
687
  return alpha ? 256 - alpha : 0;
688
}
689
690
typedef struct {
691
  unsigned position;
692
  unsigned left_up;
693
  unsigned right_down;
694
}scale_pixel;
695
696
697
static void scale_table(unsigned int start_src, unsigned int start_tar, unsigned int end_src, unsigned int end_tar, scale_pixel * table)
698
{
699
  unsigned int t;
700
  unsigned int delta_src = end_src - start_src;
701
  unsigned int delta_tar = end_tar - start_tar;
702
  int src = 0;
703
  int src_step;
704
  if (delta_src == 0 || delta_tar == 0) {
705
    return;
706
  }
707
  src_step = (delta_src << 16) / delta_tar >>1;
708
  for (t = 0; t<=delta_tar; src += (src_step << 1), t++){
1.1.4 by Mario Limonciello
Import upstream version 1.0~rc2
709
    table[t].position= FFMIN(src >> 16, end_src - 1);
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
710
    table[t].right_down = src & 0xffff;
711
    table[t].left_up = 0x10000 - table[t].right_down;
712
  }
713
}
714
715
/* bilinear scale, similar to vobsub's code */
716
static void scale_image(int x, int y, scale_pixel* table_x, scale_pixel* table_y, spudec_handle_t * spu)
717
{
718
  int alpha[4];
719
  int color[4];
720
  unsigned int scale[4];
721
  int base = table_y[y].position * spu->stride + table_x[x].position;
722
  int scaled = y * spu->scaled_stride + x;
723
  alpha[0] = canon_alpha(spu->aimage[base]);
724
  alpha[1] = canon_alpha(spu->aimage[base + 1]);
725
  alpha[2] = canon_alpha(spu->aimage[base + spu->stride]);
726
  alpha[3] = canon_alpha(spu->aimage[base + spu->stride + 1]);
727
  color[0] = spu->image[base];
728
  color[1] = spu->image[base + 1];
729
  color[2] = spu->image[base + spu->stride];
730
  color[3] = spu->image[base + spu->stride + 1];
731
  scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0];
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
732
  if (table_y[y].left_up == 0x10000) // necessary to avoid overflow-case
733
    scale[0] = table_x[x].left_up * alpha[0];
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
734
  scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1];
735
  scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2];
736
  scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3];
737
  spu->scaled_image[scaled] = (color[0] * scale[0] + color[1] * scale[1] + color[2] * scale[2] + color[3] * scale[3])>>24;
738
  spu->scaled_aimage[scaled] = (scale[0] + scale[1] + scale[2] + scale[3]) >> 16;
739
  if (spu->scaled_aimage[scaled]){
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
740
    // ensure that MPlayer's simplified alpha-blending can not overflow
741
    spu->scaled_image[scaled] = FFMIN(spu->scaled_image[scaled], spu->scaled_aimage[scaled]);
742
    // convert to MPlayer-style alpha
743
    spu->scaled_aimage[scaled] = -spu->scaled_aimage[scaled];
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
744
  }
745
}
746
747
void sws_spu_image(unsigned char *d1, unsigned char *d2, int dw, int dh, int ds,
748
	unsigned char *s1, unsigned char *s2, int sw, int sh, int ss)
749
{
750
	struct SwsContext *ctx;
751
	static SwsFilter filter;
752
	static int firsttime = 1;
753
	static float oldvar;
754
	int i;
755
756
	if (!firsttime && oldvar != spu_gaussvar) sws_freeVec(filter.lumH);
757
	if (firsttime) {
758
		filter.lumH = filter.lumV =
759
			filter.chrH = filter.chrV = sws_getGaussianVec(spu_gaussvar, 3.0);
760
		sws_normalizeVec(filter.lumH, 1.0);
761
		firsttime = 0;
762
		oldvar = spu_gaussvar;
763
	}
764
	
1.1.3 by William Grant
Import upstream version 1.0~rc1
765
	ctx=sws_getContext(sw, sh, PIX_FMT_GRAY8, dw, dh, PIX_FMT_GRAY8, SWS_GAUSS, &filter, NULL, NULL);
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
766
	sws_scale(ctx,&s1,&ss,0,sh,&d1,&ds);
767
	for (i=ss*sh-1; i>=0; i--) if (!s2[i]) s2[i] = 255; //else s2[i] = 1;
768
	sws_scale(ctx,&s2,&ss,0,sh,&d2,&ds);
769
	for (i=ds*dh-1; i>=0; i--) if (d2[i]==0) d2[i] = 1; else if (d2[i]==255) d2[i] = 0;
770
	sws_freeContext(ctx);
771
}
772
773
void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
774
{
775
  spudec_handle_t *spu = (spudec_handle_t *)me;
776
  scale_pixel *table_x;
777
  scale_pixel *table_y;
778
779
  if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {
780
781
    // check if only forced subtitles are requested 
782
    if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ 
783
	return;
784
    }
785
786
    if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
787
	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) {
788
      if (spu->image)
789
      {
790
	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
791
		   spu->image, spu->aimage, spu->stride);
792
	spu->spu_changed = 0;
793
      }
794
    }
795
    else {
796
      if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {	/* Resizing is needed */
797
	/* scaled_x = scalex * x / 0x100
798
	   scaled_y = scaley * y / 0x100
799
	   order of operations is important because of rounding. */
800
	unsigned int scalex = 0x100 * dxs / spu->orig_frame_width;
801
	unsigned int scaley = 0x100 * dys / spu->orig_frame_height;
802
	spu->scaled_start_col = spu->start_col * scalex / 0x100;
803
	spu->scaled_start_row = spu->start_row * scaley / 0x100;
804
	spu->scaled_width = spu->width * scalex / 0x100;
805
	spu->scaled_height = spu->height * scaley / 0x100;
806
	/* Kludge: draw_alpha needs width multiple of 8 */
807
	spu->scaled_stride = (spu->scaled_width + 7) & ~7;
808
	if (spu->scaled_image_size < spu->scaled_stride * spu->scaled_height) {
809
	  if (spu->scaled_image) {
810
	    free(spu->scaled_image);
811
	    spu->scaled_image_size = 0;
812
	  }
813
	  spu->scaled_image = malloc(2 * spu->scaled_stride * spu->scaled_height);
814
	  if (spu->scaled_image) {
815
	    spu->scaled_image_size = spu->scaled_stride * spu->scaled_height;
816
	    spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size;
817
	  }
818
	}
819
	if (spu->scaled_image) {
820
	  unsigned int x, y;
821
	  if (spu->scaled_width <= 1 || spu->scaled_height <= 1) {
822
	    goto nothing_to_do;
823
	  }
824
	  switch(spu_aamode&15) {
825
	  case 4:
826
	  sws_spu_image(spu->scaled_image, spu->scaled_aimage,
827
		  spu->scaled_width, spu->scaled_height, spu->scaled_stride,
828
		  spu->image, spu->aimage, spu->width, spu->height, spu->stride);
829
	  break;
830
	  case 3:
831
	  table_x = calloc(spu->scaled_width, sizeof(scale_pixel));
832
	  table_y = calloc(spu->scaled_height, sizeof(scale_pixel));
833
	  if (!table_x || !table_y) {
834
	    mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: spudec_draw_scaled: calloc failed\n");
835
	  }
836
	  scale_table(0, 0, spu->width - 1, spu->scaled_width - 1, table_x);
837
	  scale_table(0, 0, spu->height - 1, spu->scaled_height - 1, table_y);
838
	  for (y = 0; y < spu->scaled_height; y++)
839
	    for (x = 0; x < spu->scaled_width; x++)
840
	      scale_image(x, y, table_x, table_y, spu);
841
	  free(table_x);
842
	  free(table_y);
843
	  break;
844
	  case 0:
845
	  /* no antialiasing */
846
	  for (y = 0; y < spu->scaled_height; ++y) {
847
	    int unscaled_y = y * 0x100 / scaley;
848
	    int strides = spu->stride * unscaled_y;
849
	    int scaled_strides = spu->scaled_stride * y;
850
	    for (x = 0; x < spu->scaled_width; ++x) {
851
	      int unscaled_x = x * 0x100 / scalex;
852
	      spu->scaled_image[scaled_strides + x] = spu->image[strides + unscaled_x];
853
	      spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x];
854
	    }
855
	  }
856
	  break;
857
	  case 1:
858
	  {
859
	    /* Intermediate antialiasing. */
860
	    for (y = 0; y < spu->scaled_height; ++y) {
861
	      const unsigned int unscaled_top = y * spu->orig_frame_height / dys;
862
	      unsigned int unscaled_bottom = (y + 1) * spu->orig_frame_height / dys;
863
	      if (unscaled_bottom >= spu->height)
864
		unscaled_bottom = spu->height - 1;
865
	      for (x = 0; x < spu->scaled_width; ++x) {
866
		const unsigned int unscaled_left = x * spu->orig_frame_width / dxs;
867
		unsigned int unscaled_right = (x + 1) * spu->orig_frame_width / dxs;
868
		unsigned int color = 0;
869
		unsigned int alpha = 0;
870
		unsigned int walkx, walky;
871
		unsigned int base, tmp;
872
		if (unscaled_right >= spu->width)
873
		  unscaled_right = spu->width - 1;
874
		for (walky = unscaled_top; walky <= unscaled_bottom; ++walky)
875
		  for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) {
876
		    base = walky * spu->stride + walkx;
877
		    tmp = canon_alpha(spu->aimage[base]);
878
		    alpha += tmp;
879
		    color += tmp * spu->image[base];
880
		  }
881
		base = y * spu->scaled_stride + x;
882
		spu->scaled_image[base] = alpha ? color / alpha : 0;
883
		spu->scaled_aimage[base] =
884
		  alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left);
885
		/* spu->scaled_aimage[base] =
886
		  alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */
887
		if (spu->scaled_aimage[base]) {
888
		  spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base];
889
		  if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255)
890
		    spu->scaled_image[base] = 256 - spu->scaled_aimage[base];
891
		}
892
	      }
893
	    }
894
	  }
895
	  break;
896
	  case 2:
897
	  {
898
	    /* Best antialiasing.  Very slow. */
899
	    /* Any pixel (x, y) represents pixels from the original
900
	       rectangular region comprised between the columns
901
	       unscaled_y and unscaled_y + 0x100 / scaley and the rows
902
	       unscaled_x and unscaled_x + 0x100 / scalex
903
904
	       The original rectangular region that the scaled pixel
905
	       represents is cut in 9 rectangular areas like this:
906
	       
907
	       +---+-----------------+---+
908
	       | 1 |        2        | 3 |
909
	       +---+-----------------+---+
910
	       |   |                 |   |
911
	       | 4 |        5        | 6 |
912
	       |   |                 |   |
913
	       +---+-----------------+---+
914
	       | 7 |        8        | 9 |
915
	       +---+-----------------+---+
916
917
	       The width of the left column is at most one pixel and
918
	       it is never null and its right column is at a pixel
919
	       boundary.  The height of the top row is at most one
920
	       pixel it is never null and its bottom row is at a
921
	       pixel boundary. The width and height of region 5 are
922
	       integral values.  The width of the right column is
923
	       what remains and is less than one pixel.  The height
924
	       of the bottom row is what remains and is less than
925
	       one pixel.
926
927
	       The row above 1, 2, 3 is unscaled_y.  The row between
928
	       1, 2, 3 and 4, 5, 6 is top_low_row.  The row between 4,
929
	       5, 6 and 7, 8, 9 is (unsigned int)unscaled_y_bottom.
930
	       The row beneath 7, 8, 9 is unscaled_y_bottom.
931
932
	       The column left of 1, 4, 7 is unscaled_x.  The column
933
	       between 1, 4, 7 and 2, 5, 8 is left_right_column.  The
934
	       column between 2, 5, 8 and 3, 6, 9 is (unsigned
935
	       int)unscaled_x_right.  The column right of 3, 6, 9 is
936
	       unscaled_x_right. */
937
	    const double inv_scalex = (double) 0x100 / scalex;
938
	    const double inv_scaley = (double) 0x100 / scaley;
939
	    for (y = 0; y < spu->scaled_height; ++y) {
940
	      const double unscaled_y = y * inv_scaley;
941
	      const double unscaled_y_bottom = unscaled_y + inv_scaley;
1.1.4 by Mario Limonciello
Import upstream version 1.0~rc2
942
	      const unsigned int top_low_row = FFMIN(unscaled_y_bottom, unscaled_y + 1.0);
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
943
	      const double top = top_low_row - unscaled_y;
944
	      const unsigned int height = unscaled_y_bottom > top_low_row
945
		? (unsigned int) unscaled_y_bottom - top_low_row
946
		: 0;
947
	      const double bottom = unscaled_y_bottom > top_low_row
948
		? unscaled_y_bottom - floor(unscaled_y_bottom)
949
		: 0.0;
950
	      for (x = 0; x < spu->scaled_width; ++x) {
951
		const double unscaled_x = x * inv_scalex;
952
		const double unscaled_x_right = unscaled_x + inv_scalex;
1.1.4 by Mario Limonciello
Import upstream version 1.0~rc2
953
		const unsigned int left_right_column = FFMIN(unscaled_x_right, unscaled_x + 1.0);
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
954
		const double left = left_right_column - unscaled_x;
955
		const unsigned int width = unscaled_x_right > left_right_column
956
		  ? (unsigned int) unscaled_x_right - left_right_column
957
		  : 0;
958
		const double right = unscaled_x_right > left_right_column
959
		  ? unscaled_x_right - floor(unscaled_x_right)
960
		  : 0.0;
961
		double color = 0.0;
962
		double alpha = 0.0;
963
		double tmp;
964
		unsigned int base;
965
		/* Now use these informations to compute a good alpha,
966
                   and lightness.  The sum is on each of the 9
967
                   region's surface and alpha and lightness.
968
969
		  transformed alpha = sum(surface * alpha) / sum(surface)
970
		  transformed color = sum(surface * alpha * color) / sum(surface * alpha)
971
		*/
972
		/* 1: top left part */
973
		base = spu->stride * (unsigned int) unscaled_y;
974
		tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]);
975
		alpha += tmp;
976
		color += tmp * spu->image[base + (unsigned int) unscaled_x];
977
		/* 2: top center part */
978
		if (width > 0) {
979
		  unsigned int walkx;
980
		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
981
		    base = spu->stride * (unsigned int) unscaled_y + walkx;
982
		    tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]);
983
		    alpha += tmp;
984
		    color += tmp * spu->image[base];
985
		  }
986
		}
987
		/* 3: top right part */
988
		if (right > 0.0) {
989
		  base = spu->stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right;
990
		  tmp = right * top * canon_alpha(spu->aimage[base]);
991
		  alpha += tmp;
992
		  color += tmp * spu->image[base];
993
		}
994
		/* 4: center left part */
995
		if (height > 0) {
996
		  unsigned int walky;
997
		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
998
		    base = spu->stride * walky + (unsigned int) unscaled_x;
999
		    tmp = left /* * 1.0 */ * canon_alpha(spu->aimage[base]);
1000
		    alpha += tmp;
1001
		    color += tmp * spu->image[base];
1002
		  }
1003
		}
1004
		/* 5: center part */
1005
		if (width > 0 && height > 0) {
1006
		  unsigned int walky;
1007
		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
1008
		    unsigned int walkx;
1009
		    base = spu->stride * walky;
1010
		    for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
1011
		      tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimage[base + walkx]);
1012
		      alpha += tmp;
1013
		      color += tmp * spu->image[base + walkx];
1014
		    }
1015
		  }		    
1016
		}
1017
		/* 6: center right part */
1018
		if (right > 0.0 && height > 0) {
1019
		  unsigned int walky;
1020
		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
1021
		    base = spu->stride * walky + (unsigned int) unscaled_x_right;
1022
		    tmp = right /* * 1.0 */ * canon_alpha(spu->aimage[base]);
1023
		    alpha += tmp;
1024
		    color += tmp * spu->image[base];
1025
		  }
1026
		}
1027
		/* 7: bottom left part */
1028
		if (bottom > 0.0) {
1029
		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x;
1030
		  tmp = left * bottom * canon_alpha(spu->aimage[base]);
1031
		  alpha += tmp;
1032
		  color += tmp * spu->image[base];
1033
		}
1034
		/* 8: bottom center part */
1035
		if (width > 0 && bottom > 0.0) {
1036
		  unsigned int walkx;
1037
		  base = spu->stride * (unsigned int) unscaled_y_bottom;
1038
		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
1039
		    tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimage[base + walkx]);
1040
		    alpha += tmp;
1041
		    color += tmp * spu->image[base + walkx];
1042
		  }
1043
		}
1044
		/* 9: bottom right part */
1045
		if (right > 0.0 && bottom > 0.0) {
1046
		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x_right;
1047
		  tmp = right * bottom * canon_alpha(spu->aimage[base]);
1048
		  alpha += tmp;
1049
		  color += tmp * spu->image[base];
1050
		}
1051
		/* Finally mix these transparency and brightness information suitably */
1052
		base = spu->scaled_stride * y + x;
1053
		spu->scaled_image[base] = alpha > 0 ? color / alpha : 0;
1054
		spu->scaled_aimage[base] = alpha * scalex * scaley / 0x10000;
1055
		if (spu->scaled_aimage[base]) {
1056
		  spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base];
1057
		  if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255)
1058
		    spu->scaled_image[base] = 256 - spu->scaled_aimage[base];
1059
		}
1060
	      }
1061
	    }
1062
	  }
1063
	  }
1064
nothing_to_do:
1065
	  /* Kludge: draw_alpha needs width multiple of 8. */
1066
	  if (spu->scaled_width < spu->scaled_stride)
1067
	    for (y = 0; y < spu->scaled_height; ++y) {
1068
	      memset(spu->scaled_aimage + y * spu->scaled_stride + spu->scaled_width, 0,
1069
		     spu->scaled_stride - spu->scaled_width);
1070
	    }
1071
	  spu->scaled_frame_width = dxs;
1072
	  spu->scaled_frame_height = dys;
1073
	}
1074
      }
1075
      if (spu->scaled_image){
1076
        switch (spu_alignment) {
1077
        case 0:
1078
          spu->scaled_start_row = dys*sub_pos/100;
1079
	  if (spu->scaled_start_row + spu->scaled_height > dys)
1080
	    spu->scaled_start_row = dys - spu->scaled_height;
1081
	  break;
1082
	case 1:
1083
          spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height/2;
1.1.4 by Mario Limonciello
Import upstream version 1.0~rc2
1084
	  if (sub_pos >= 50 && spu->scaled_start_row + spu->scaled_height > dys)
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1085
	      spu->scaled_start_row = dys - spu->scaled_height;
1086
	  break;
1087
        case 2:
1088
          spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height;
1089
	  break;
1090
	}
1091
	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
1092
		   spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
1093
	spu->spu_changed = 0;
1094
      }
1095
    }
1096
  }
1097
  else
1098
  {
1099
    mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPU not displayed: start_pts=%d  end_pts=%d  now_pts=%d\n",
1100
        spu->start_pts, spu->end_pts, spu->now_pts);
1101
  }
1102
}
1103
1104
void spudec_update_palette(void * this, unsigned int *palette)
1105
{
1106
  spudec_handle_t *spu = (spudec_handle_t *) this;
1107
  if (spu && palette) {
1108
    memcpy(spu->global_palette, palette, sizeof(spu->global_palette));
1109
    if(spu->hw_spu)
1110
      spu->hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette);
1111
  }
1112
}
1113
1114
void spudec_set_font_factor(void * this, double factor)
1115
{
1116
  spudec_handle_t *spu = (spudec_handle_t *) this;
1117
  spu->font_start_level = (int)(0xF0-(0xE0*factor));
1118
}
1119
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
1120
static void spudec_parse_extradata(spudec_handle_t *this,
1121
                                   uint8_t *extradata, int extradata_len)
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1122
{
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
1123
  uint8_t *buffer, *ptr;
1124
  unsigned int *pal = this->global_palette, *cuspal = this->cuspal;
1125
  unsigned int tridx;
1126
  int i;
1127
1128
  if (extradata_len == 16*4) {
1129
    for (i=0; i<16; i++)
1130
      pal[i] = AV_RB32(extradata + i*4);
1131
    this->auto_palette = 0;
1132
    return;
1133
  }
1134
1135
  if (!(ptr = buffer = malloc(extradata_len+1)))
1136
    return;
1137
  memcpy(buffer, extradata, extradata_len);
1138
  buffer[extradata_len] = 0;
1139
1140
  do {
1141
    sscanf(ptr, "size: %dx%d", &this->orig_frame_width, &this->orig_frame_height);
1142
    if (sscanf(ptr, "palette: %x, %x, %x, %x, %x, %x, %x, %x,"
1143
                            " %x, %x, %x, %x, %x, %x, %x, %x",
1144
               &pal[ 0], &pal[ 1], &pal[ 2], &pal[ 3],
1145
               &pal[ 4], &pal[ 5], &pal[ 6], &pal[ 7],
1146
               &pal[ 8], &pal[ 9], &pal[10], &pal[11],
1147
               &pal[12], &pal[13], &pal[14], &pal[15]) == 16) {
1148
      for (i=0; i<16; i++)
1149
        pal[i] = vobsub_palette_to_yuv(pal[i]);
1150
      this->auto_palette = 0;
1151
    }
1152
    if (!strncasecmp(ptr, "forced subs: on", 15))
1153
      this->forced_subs_only = 1;
1154
    if (sscanf(ptr, "custom colors: ON, tridx: %x, colors: %x, %x, %x, %x",
1155
               &tridx, cuspal+0, cuspal+1, cuspal+2, cuspal+3) == 5) {
1156
      for (i=0; i<4; i++) {
1157
        cuspal[i] = vobsub_rgb_to_yuv(cuspal[i]);
1158
        if (tridx & (1 << (12-4*i)))
1159
          cuspal[i] |= 1 << 31;
1160
      }
1161
      this->custom = 1;
1162
    }
1163
  } while ((ptr=strchr(ptr,'\n')) && *++ptr);
1164
1165
  free(buffer);
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1166
}
1167
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
1168
void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len)
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1169
{
1170
  spudec_handle_t *this = calloc(1, sizeof(spudec_handle_t));
1171
  if (this){
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
1172
    this->orig_frame_height = frame_height;
1173
    // set up palette:
1174
    if (palette)
1175
      memcpy(this->global_palette, palette, sizeof(this->global_palette));
1176
    else
1177
      this->auto_palette = 1;
1178
    if (extradata)
1179
      spudec_parse_extradata(this, extradata, extradata_len);
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1180
    /* XXX Although the video frame is some size, the SPU frame is
1181
       always maximum size i.e. 720 wide and 576 or 480 high */
1182
    this->orig_frame_width = 720;
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
1183
    if (this->orig_frame_height == 480 || this->orig_frame_height == 240)
1184
      this->orig_frame_height = 480;
1185
    else
1186
      this->orig_frame_height = 576;
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1187
  }
1188
  else
1189
    mp_msg(MSGT_SPUDEC,MSGL_FATAL, "FATAL: spudec_init: calloc");
1190
  return this;
1191
}
1192
1193
void *spudec_new(unsigned int *palette)
1194
{
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
1195
    return spudec_new_scaled(palette, 0, 0, NULL, 0);
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1196
}
1197
1198
void spudec_free(void *this)
1199
{
1200
  spudec_handle_t *spu = (spudec_handle_t*)this;
1201
  if (spu) {
1202
    while (spu->queue_head)
1203
      spudec_free_packet(spudec_dequeue_packet(spu));
1204
    if (spu->packet)
1205
      free(spu->packet);
1206
    if (spu->scaled_image)
1207
	free(spu->scaled_image);
1208
    if (spu->image)
1209
      free(spu->image);
1210
    free(spu);
1211
  }
1212
}
1213
0.2.1 by Reinhard Tartler
Import upstream version 1.0~rc2+svn20090303
1214
void spudec_set_hw_spu(void *this, const vo_functions_t *hw_spu)
1 by Sebastian Dröge
Import upstream version 0.99+1.0pre7try2+cvs20051205
1215
{
1216
  spudec_handle_t *spu = (spudec_handle_t*)this;
1217
  if (!spu)
1218
    return;
1219
  spu->hw_spu = hw_spu;
1220
  hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette);
1221
}