/*
* Skeleton of function spudec_process_controll() is from xine sources.
* Further works:
* LGB,... (yeah, try to improve it and insert your name here! ;-)
*
* Kim Minh Kaplan
* implement fragments reassembly, RLE decoding.
* read brightness from the IFO.
*
* For information on SPU format see <URL:http://sam.zoy.org/doc/dvd/subtitles/>
* and <URL:http://members.aol.com/mpucoder/DVD/spu.html>
*
* This file is part of MPlayer.
*
* MPlayer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* MPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <libavutil/common.h>
#include <libavutil/intreadwrite.h>
#include <libswscale/swscale.h>
#include "config.h"
#include "mp_msg.h"
#include "spudec.h"
#include "vobsub.h"
#include "sub.h"
#include "mpcommon.h"
/* Valid values for spu_aamode:
0: none (fastest, most ugly)
1: approximate
2: full (slowest)
3: bilinear (similiar to vobsub, fast and not too bad)
4: uses swscaler gaussian (this is the only one that looks good)
*/
int spu_aamode = 3;
int spu_alignment = -1;
float spu_gaussvar = 1.0;
typedef struct spu_packet_t packet_t;
struct spu_packet_t {
int is_decoded;
unsigned char *packet;
int data_len;
unsigned int palette[4];
unsigned int alpha[4];
unsigned int control_start; /* index of start of control data */
unsigned int current_nibble[2]; /* next data nibble (4 bits) to be
processed (for RLE decoding) for
even and odd lines */
int deinterlace_oddness; /* 0 or 1, index into current_nibble */
unsigned int start_col;
unsigned int start_row;
unsigned int width, height, stride;
unsigned int start_pts, end_pts;
packet_t *next;
};
struct palette_crop_cache {
int valid;
uint32_t palette;
int sx, sy, ex, ey;
int result;
};
typedef struct {
packet_t *queue_head;
packet_t *queue_tail;
unsigned int global_palette[16];
unsigned int orig_frame_width, orig_frame_height;
unsigned char* packet;
size_t packet_reserve; /* size of the memory pointed to by packet */
unsigned int packet_offset; /* end of the currently assembled fragment */
unsigned int packet_size; /* size of the packet once all fragments are assembled */
int packet_pts; /* PTS for this packet */
unsigned int palette[4];
unsigned int alpha[4];
unsigned int cuspal[4];
unsigned int custom;
unsigned int now_pts;
unsigned int start_pts, end_pts;
unsigned int start_col;
unsigned int start_row;
unsigned int width, height, stride;
size_t image_size; /* Size of the image buffer */
unsigned char *image; /* Grayscale value */
unsigned char *aimage; /* Alpha value */
unsigned int pal_start_col, pal_start_row;
unsigned int pal_width, pal_height;
unsigned char *pal_image; /* palette entry value */
unsigned int scaled_frame_width, scaled_frame_height;
unsigned int scaled_start_col, scaled_start_row;
unsigned int scaled_width, scaled_height, scaled_stride;
size_t scaled_image_size;
unsigned char *scaled_image;
unsigned char *scaled_aimage;
int auto_palette; /* 1 if we lack a palette and must use an heuristic. */
int font_start_level; /* Darkest value used for the computed font */
int spu_changed;
unsigned int forced_subs_only; /* flag: 0=display all subtitle, !0 display only forced subtitles */
unsigned int is_forced_sub; /* true if current subtitle is a forced subtitle */
struct palette_crop_cache palette_crop_cache;
struct old_osd_planar borrowed_sub_image;
struct sub_bitmap sub_part, borrowed_sub_part;
struct osd_bmp_indexed borrowed_bmp;
} spudec_handle_t;
static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
{
if (this->queue_head == NULL)
this->queue_head = packet;
else
this->queue_tail->next = packet;
this->queue_tail = packet;
}
static packet_t *spudec_dequeue_packet(spudec_handle_t *this)
{
packet_t *retval = this->queue_head;
this->queue_head = retval->next;
if (this->queue_head == NULL)
this->queue_tail = NULL;
return retval;
}
static void spudec_free_packet(packet_t *packet)
{
free(packet->packet);
free(packet);
}
static inline unsigned int get_be16(const unsigned char *p)
{
return (p[0] << 8) + p[1];
}
static inline unsigned int get_be24(const unsigned char *p)
{
return (get_be16(p) << 8) + p[2];
}
static void next_line(packet_t *packet)
{
if (packet->current_nibble[packet->deinterlace_oddness] % 2)
packet->current_nibble[packet->deinterlace_oddness]++;
packet->deinterlace_oddness = (packet->deinterlace_oddness + 1) % 2;
}
static inline unsigned char get_nibble(packet_t *packet)
{
unsigned char nib;
unsigned int *nibblep = packet->current_nibble + packet->deinterlace_oddness;
if (*nibblep / 2 >= packet->control_start) {
mp_msg(MSGT_SPUDEC,MSGL_WARN, "SPUdec: ERROR: get_nibble past end of packet\n");
return 0;
}
nib = packet->packet[*nibblep / 2];
if (*nibblep % 2)
nib &= 0xf;
else
nib >>= 4;
++*nibblep;
return nib;
}
/* Cut the sub to visible part */
static inline void spudec_cut_image(spudec_handle_t *this)
{
unsigned int fy, ly;
unsigned int first_y, last_y;
if (this->stride == 0 || this->height == 0) {
return;
}
for (fy = 0; fy < this->image_size && !this->aimage[fy]; fy++);
for (ly = this->stride * this->height-1; ly && !this->aimage[ly]; ly--);
first_y = fy / this->stride;
last_y = ly / this->stride;
//printf("first_y: %d, last_y: %d\n", first_y, last_y);
this->start_row += firs
|