Improvment for spu subtitles.

Removed the integreted spudec in vobsub.
Various cleanup/bugfix in vobsub (no more auto palette when a true one is
here)
HW spu rendering moved in spudec because we first need to reassable the
packet before sending them to the hw.
Spudec is now created only if nedded.


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6111 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
albeu 2002-05-17 23:47:27 +00:00
parent 517a1ee64f
commit 7562937d95
10 changed files with 191 additions and 158 deletions

View File

@ -390,12 +390,6 @@ int vo_update_osd(int dxs,int dys){
else
obj->flags&=~OSDFLAG_VISIBLE;
break;
case OSDTYPE_VOBSUB:
if(vo_vobsub)
obj->flags|=OSDFLAG_VISIBLE|OSDFLAG_CHANGED;
else
obj->flags&=~OSDFLAG_VISIBLE;
break;
case OSDTYPE_OSD:
if(vo_font && vo_osd_text && vo_osd_text[0]){
vo_update_text_osd(obj,dxs,dys); // update bbox
@ -443,13 +437,12 @@ void vo_init_osd(){
draw_alpha_init_flag=1;
vo_draw_alpha_init();
}
if(vo_osd_list) free_osd_list;
if(vo_osd_list) free_osd_list();
// temp hack, should be moved to mplayer/mencoder later
new_osd_obj(OSDTYPE_OSD);
new_osd_obj(OSDTYPE_SUBTITLE);
new_osd_obj(OSDTYPE_PROGBAR);
new_osd_obj(OSDTYPE_SPU);
new_osd_obj(OSDTYPE_VOBSUB);
}
int vo_osd_changed_flag=0;
@ -482,9 +475,6 @@ void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h,
case OSDTYPE_SPU:
spudec_draw_scaled(vo_spudec, dxs, dys, draw_alpha); // FIXME
break;
case OSDTYPE_VOBSUB:
vobsub_draw(vo_vobsub, dxs, dys, draw_alpha); // FIXME
break;
case OSDTYPE_OSD:
vo_draw_text_osd(obj,draw_alpha);
break;

View File

@ -10,7 +10,6 @@ typedef struct mp_osd_bbox_s {
#define OSDTYPE_SUBTITLE 2
#define OSDTYPE_PROGBAR 3
#define OSDTYPE_SPU 4
#define OSDTYPE_VOBSUB 5
#define OSDFLAG_VISIBLE 1
#define OSDFLAG_CHANGED 2

View File

@ -39,6 +39,7 @@
/* libmpcodecs direct rendering: */
#define VOCTRL_GET_IMAGE 9
#define VOCTRL_DRAW_IMAGE 13
#define VOCTRL_SET_SPU_PALETTE 14
/* decoding ahead: */
#define VOCTRL_GET_NUM_FRAMES 10
#define VOCTRL_GET_FRAME_NUM 11

View File

@ -508,7 +508,7 @@ if(sh_audio && (out_audio_codec || seek_to_sec || !sh_audio->wf)){
if (spudec_ifo) {
unsigned int palette[16], width, height;
if (vobsub_parse_ifo(spudec_ifo, palette, &width, &height, 1) >= 0)
if (vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1) >= 0)
vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h);
}
#ifdef USE_DVDREAD

View File

@ -78,6 +78,8 @@ extern int verbose; // defined in mplayer.c
#define MSGT_SWS 34
#define MSGT_VOBSUB 35
#define MSGT_MAX 64
void mp_msg_init();

View File

@ -279,6 +279,7 @@ static unsigned int inited_flags=0;
#define INITED_SPUDEC 32
#define INITED_STREAM 64
#define INITED_INPUT 128
#define INITED_VOBSUB 256
#define INITED_ALL 0xFFFF
void uninit_player(unsigned int mask){
@ -310,6 +311,13 @@ void uninit_player(unsigned int mask){
getch2_disable();
}
if(mask&INITED_VOBSUB){
inited_flags&=~INITED_VOBSUB;
current_module="uninit_vobsub";
vobsub_close(vo_vobsub);
vo_vobsub=NULL;
}
if (mask&INITED_SPUDEC){
inited_flags&=~INITED_SPUDEC;
current_module="uninit_spudec";
@ -854,7 +862,7 @@ if(!use_stdin && !slave_mode){
current_module="vobsub";
if (vobsub_name){
vo_vobsub=vobsub_open(vobsub_name,1);
vo_vobsub=vobsub_open(vobsub_name,spudec_ifo,1,&vo_spudec);
if(vo_vobsub==NULL)
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,vobsub_name);
}else if(sub_auto && filename && (strlen(filename)>=5)){
@ -862,7 +870,7 @@ if(!use_stdin && !slave_mode){
char *buf = malloc((strlen(filename)-3) * sizeof(char));
memset(buf,0,strlen(filename)-3); // make sure string is terminated
strncpy(buf, filename, strlen(filename)-4);
vo_vobsub=vobsub_open(buf,0);
vo_vobsub=vobsub_open(buf,spudec_ifo,0,&vo_spudec);
free(buf);
}
if(vo_vobsub)
@ -1149,12 +1157,12 @@ if(!sh_video && !sh_audio){
demux_info_print(demuxer);
//================== Read SUBTITLES (DVD & TEXT) ==========================
if(sh_video){
if(d_dvdsub->id >= 0 && vo_spudec==NULL && sh_video){
if (spudec_ifo) {
unsigned int palette[16], width, height;
current_module="spudec_init_vobsub";
if (vobsub_parse_ifo(spudec_ifo, palette, &width, &height, 1) >= 0)
if (vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1) >= 0)
vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h);
}
@ -1177,13 +1185,16 @@ if (vo_spudec==NULL && stream->type==STREAMTYPE_DVD) {
if (vo_spudec==NULL) {
current_module="spudec_init_normal";
vo_spudec=spudec_new_scaled(NULL, sh_video->disp_w, sh_video->disp_h);
spudec_set_font_factor(font_factor);
spudec_set_font_factor(vo_spudec,font_factor);
}
if (vo_spudec!=NULL)
inited_flags|=INITED_SPUDEC;
}
#ifdef USE_SUB
if(sh_video) {
// after reading video params we should load subtitles because
// we know fps so now we can adjust subtitles time to ~6 seconds AST
// check .sub
@ -1198,9 +1209,9 @@ if (vo_spudec!=NULL)
}
if(subtitles && stream_dump_type==3) list_sub_file(subtitles);
if(subtitles && stream_dump_type==4) dump_mpsub(subtitles, sh_video->fps);
#endif
}
#endif
//================== Init AUDIO (codec) ==========================
current_module="find_audio_codec";
@ -1335,6 +1346,9 @@ current_module="init_vo_vaa";
}
}
if(vo_flags & 0x08 && vo_spudec)
spudec_set_hw_spu(vo_spudec,video_out);
//================== MAIN: ==========================
main:
if(!sh_video) osd_level = 0;
@ -2896,42 +2910,43 @@ if(rel_seek_secs || abs_seek_pos){
}
#endif
// VobSub subtitles
if(vo_vobsub){
current_module="vobsub";
if(d_video->pts+sub_delay>=0)
vobsub_process(vo_vobsub,d_video->pts+sub_delay);
/* Don't know how to detect wether the sub has changed or not */
vo_osd_changed(OSDTYPE_VOBSUB);
current_module=NULL;
}
// DVD sub:
if(vo_flags & 0x08){
static vo_mpegpes_t packet;
static vo_mpegpes_t *pkg=&packet;
packet.timestamp=sh_video->timer*90000.0;
packet.id=0x20; /* Subpic */
while((packet.size=ds_get_packet_sub(d_dvdsub,&packet.data))>0){
mp_msg(MSGT_CPLAYER,MSGL_V,"\rDVD sub: len=%d v_pts=%5.3f s_pts=%5.3f \n",packet.size,d_video->pts,d_dvdsub->pts);
if(vo_config_count) video_out->draw_frame(&pkg);
if(vo_config_count && vo_spudec) {
unsigned char* packet=NULL;
int len,timestamp;
// Get a sub packet from the dvd or a vobsub and make a timestamp relative to sh_video->timer
int get_sub_packet(void) {
// Vobsub
len = 0;
if(vo_vobsub) {
if(d_video->pts+sub_delay>=0) {
// The + next_frame_time is there because we'll display the sub at the next frame
len = vobsub_get_packet(vo_vobsub,d_video->pts+sub_delay+next_frame_time,(void**)&packet,&timestamp);
if(len > 0) {
timestamp -= (d_video->pts + sub_delay - sh_video->timer)*90000;
mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,d_video->pts,sh_video->timer,timestamp / 90000.0);
}
}
} else {
// DVD sub
len = ds_get_packet_sub(d_dvdsub,(unsigned char**)&packet);
if(len > 0) {
timestamp = 90000*(sh_video->timer + d_dvdsub->pts + sub_delay - d_video->pts);
mp_dbg(MSGT_CPLAYER,MSGL_V,"\rDVD sub: len=%d v_pts=%5.3f s_pts=%5.3f ts=%d \n",len,d_video->pts,d_dvdsub->pts,timestamp);
}
}
}else if(vo_spudec){
unsigned char* packet=NULL;
int len;
current_module="spudec";
while((len=ds_get_packet_sub(d_dvdsub,&packet))>0){
mp_msg(MSGT_CPLAYER,MSGL_V,"\rDVD sub: len=%d v_pts=%5.3f s_pts=%5.3f \n",len,d_video->pts,d_dvdsub->pts);
spudec_assemble(vo_spudec,packet,len,90000*d_dvdsub->pts);
}
spudec_heartbeat(vo_spudec,90000*d_video->pts);
/* Don't know how to detect wether the sub has changed or not */
vo_osd_changed(OSDTYPE_SPU);
current_module=NULL;
return len;
}
current_module="spudec";
spudec_heartbeat(vo_spudec,90000*sh_video->timer);
while(get_sub_packet()>0 && packet){
spudec_assemble(vo_spudec,packet,len,timestamp);
}
/* Don't know how to detect wether the sub has changed or not */
vo_osd_changed(OSDTYPE_SPU);
current_module=NULL;
}
} // while(!eof)

View File

@ -29,6 +29,7 @@
#if ANTIALIASING_ALGORITHM == 2
#include <math.h>
#endif
#include "libvo/video_out.h"
#include "spudec.h"
#define MIN(a, b) ((a)<(b)?(a):(b))
@ -63,12 +64,11 @@ typedef struct {
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 */
vo_functions_t *hw_spu;
} spudec_handle_t;
/* 1 if we lack a palette and must use an heuristic. */
static int auto_palette = 0;
/* Darkest value used for the computed font */
static int font_start_level = 0;
static inline unsigned int get_be16(const unsigned char *p)
{
@ -219,8 +219,8 @@ static void compute_palette(spudec_handle_t *this)
start = 0x80;
step = 0;
} else {
start = font_start_level;
step = (0xF0-font_start_level)/(cused-1);
start = this->font_start_level;
step = (0xF0-this->font_start_level)/(cused-1);
}
memset(used, 0, sizeof(used));
for (i=0; i<4; i++) {
@ -286,7 +286,10 @@ static void spudec_process_control(spudec_handle_t *this, unsigned int pts100)
this->alpha[1] = this->packet[off] & 0xf;
this->alpha[2] = this->packet[off + 1] >> 4;
this->alpha[3] = this->packet[off + 1] & 0xf;
if (auto_palette) compute_palette(this);
if (this->auto_palette) {
compute_palette(this);
this->auto_palette = 0;
}
mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Alpha %d, %d, %d, %d\n",
this->alpha[0], this->alpha[1], this->alpha[2], this->alpha[3]);
off+=2;
@ -333,8 +336,17 @@ static void spudec_process_control(spudec_handle_t *this, unsigned int pts100)
static void spudec_decode(spudec_handle_t *this, unsigned int pts100)
{
spudec_process_control(this, pts100);
spudec_process_data(this);
if(this->hw_spu) {
static vo_mpegpes_t packet = { NULL, 0, 0x20, 0 };
static vo_mpegpes_t *pkg=&packet;
packet.data = this->packet;
packet.size = this->packet_size;
packet.timestamp = pts100;
this->hw_spu->draw_frame((uint8_t**)&pkg);
} else {
spudec_process_control(this, pts100);
spudec_process_data(this);
}
}
@ -721,13 +733,17 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra
void spudec_update_palette(void * this, unsigned int *palette)
{
spudec_handle_t *spu = (spudec_handle_t *) this;
if (spu && palette)
if (spu && palette) {
memcpy(spu->global_palette, palette, sizeof(spu->global_palette));
if(spu->hw_spu)
spu->hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette);
}
}
void spudec_set_font_factor(double factor)
void spudec_set_font_factor(void * this, double factor)
{
font_start_level = (int)(0xF0-(0xE0*factor));
spudec_handle_t *spu = (spudec_handle_t *) this;
spu->font_start_level = (int)(0xF0-(0xE0*factor));
}
void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height)
@ -736,11 +752,11 @@ void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigne
if (this) {
if (palette) {
memcpy(this->global_palette, palette, sizeof(this->global_palette));
auto_palette = 0;
this->auto_palette = 0;
}
else {
/* No palette, compute one */
auto_palette = 1;
this->auto_palette = 1;
}
this->packet = NULL;
this->image = NULL;
@ -749,7 +765,7 @@ void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigne
this->orig_frame_height = frame_height;
}
else
perror("FATAL: spudec_init: calloc");
mp_msg(MSGT_SPUDEC,MSGL_FATAL, "FATAL: spudec_init: calloc");
return this;
}
@ -766,19 +782,19 @@ void *spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsi
this->orig_frame_height = frame_height;
this->custom = custom;
// set up palette:
auto_palette = 1;
this->auto_palette = 1;
if (palette){
memcpy(this->global_palette, palette, sizeof(this->global_palette));
auto_palette = 0;
this->auto_palette = 0;
}
this->custom = custom;
if (custom && cuspal) {
memcpy(this->cuspal, cuspal, sizeof(this->cuspal));
auto_palette = 0;
this->auto_palette = 0;
}
}
else
perror("FATAL: spudec_init: calloc");
mp_msg(MSGT_SPUDEC,MSGL_FATAL, "FATAL: spudec_init: calloc");
return this;
}
@ -800,3 +816,12 @@ void spudec_free(void *this)
free(spu);
}
}
void spudec_set_hw_spu(void *this, vo_functions_t *hw_spu)
{
spudec_handle_t *spu = (spudec_handle_t*)this;
if (!spu)
return;
spu->hw_spu = hw_spu;
hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette);
}

View File

@ -7,11 +7,12 @@ void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsi
void spudec_draw_scaled(void *this, 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));
void spudec_update_palette(void *this, unsigned int *palette);
void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height);
void *spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsigned int custom, unsigned int frame_width, unsigned int frame_height);
void *spudec_new(unsigned int *palette);
void spudec_free(void *this);
void spudec_reset(void *this); // called after seek
int spudec_visible(void *this); // check if spu is visible
void spudec_set_font_factor(double factor); // sets the equivalent to ffactor
void spudec_set_font_factor(void * this, double factor); // sets the equivalent to ffactor
void spudec_set_hw_spu(void *this, vo_functions_t *hw_spu);
#endif

160
vobsub.c
View File

@ -17,6 +17,7 @@
#include "stream.h"
#include "vobsub.h"
#include "libvo/video_out.h"
#include "spudec.h"
#include "mp_msg.h"
@ -165,7 +166,7 @@ mpeg_run(mpeg_t *mpeg)
else if ((c & 0xf0) == 0x20)
version = 2;
else {
fprintf(stderr, "Unsupported MPEG version: 0x%02x", c);
mp_msg(MSGT_VOBSUB,MSGL_ERR, "Unsupported MPEG version: 0x%02x", c);
return -1;
}
if (version == 4) {
@ -214,7 +215,7 @@ mpeg_run(mpeg_t *mpeg)
hdrlen = c;
dataidx = mpeg_tell(mpeg) + hdrlen;
if (dataidx > idx + len) {
fprintf(stderr, "Invalid header length: %d (total length: %d, idx: %d, dataidx: %d)\n",
mp_msg(MSGT_VOBSUB,MSGL_ERR, "Invalid header length: %d (total length: %d, idx: %d, dataidx: %d)\n",
hdrlen, len, idx, dataidx);
return -1;
}
@ -222,7 +223,7 @@ mpeg_run(mpeg_t *mpeg)
if (stream_read(mpeg->stream, buf, 5) != 5)
return -1;
if (!(((buf[0] & 0xf0) == 0x20) && (buf[0] & 1) && (buf[2] & 1) && (buf[4] & 1))) {
fprintf(stderr, "vobsub PTS error: 0x%02x %02x%02x %02x%02x \n",
mp_msg(MSGT_VOBSUB,MSGL_ERR, "vobsub PTS error: 0x%02x %02x%02x %02x%02x \n",
buf[0], buf[1], buf[2], buf[3], buf[4]);
mpeg->pts = 0;
}
@ -237,7 +238,7 @@ mpeg_run(mpeg_t *mpeg)
stream_seek(mpeg->stream, dataidx);
mpeg->aid = stream_read_char(mpeg->stream);
if (mpeg->aid < 0) {
fprintf(stderr, "Bogus aid %d\n", mpeg->aid);
mp_msg(MSGT_VOBSUB,MSGL_ERR, "Bogus aid %d\n", mpeg->aid);
return -1;
}
mpeg->packet_size = len - ((unsigned int) mpeg_tell(mpeg) - idx);
@ -249,13 +250,13 @@ mpeg_run(mpeg_t *mpeg)
mpeg->packet_reserve = mpeg->packet_size;
}
if (mpeg->packet == NULL) {
perror("malloc failure");
mp_msg(MSGT_VOBSUB,MSGL_FATAL,"malloc failure");
mpeg->packet_reserve = 0;
mpeg->packet_size = 0;
return -1;
}
if (stream_read(mpeg->stream, mpeg->packet, mpeg->packet_size) != mpeg->packet_size) {
perror("stream_read failure");
if ((unsigned int)stream_read(mpeg->stream, mpeg->packet, mpeg->packet_size) != mpeg->packet_size) {
mp_msg(MSGT_VOBSUB,MSGL_ERR,"stream_read failure");
mpeg->packet_size = 0;
return -1;
}
@ -280,7 +281,7 @@ mpeg_run(mpeg_t *mpeg)
}
else {
fprintf(stderr, "unknown header 0x%02X%02X%02X%02X\n",
mp_msg(MSGT_VOBSUB,MSGL_ERR,"unknown header 0x%02X%02X%02X%02X\n",
buf[0], buf[1], buf[2], buf[3]);
return -1;
}
@ -353,7 +354,7 @@ packet_queue_ensure(packet_queue_t *queue, unsigned int needed_size)
if (queue->packets) {
packet_t *tmp = realloc(queue->packets, 2 * queue->packets_reserve * sizeof(packet_t));
if (tmp == NULL) {
perror("realloc failure");
mp_msg(MSGT_VOBSUB,MSGL_FATAL,"realloc failure");
return -1;
}
queue->packets = tmp;
@ -362,7 +363,7 @@ packet_queue_ensure(packet_queue_t *queue, unsigned int needed_size)
else {
queue->packets = malloc(sizeof(packet_t));
if (queue->packets == NULL) {
perror("malloc failure");
mp_msg(MSGT_VOBSUB,MSGL_FATAL,"malloc failure");
return -1;
}
queue->packets_reserve = 1;
@ -407,7 +408,6 @@ packet_queue_insert(packet_queue_t *queue)
**********************************************************************/
typedef struct {
void *spudec;
unsigned int palette[16];
unsigned int cuspal[4];
int delay;
@ -430,7 +430,7 @@ vobsub_ensure_spu_stream(vobsub_t *vob, unsigned int index)
if (vob->spu_streams) {
packet_queue_t *tmp = realloc(vob->spu_streams, (index + 1) * sizeof(packet_queue_t));
if (tmp == NULL) {
perror("vobsub_ensure_spu_stream: realloc failure");
mp_msg(MSGT_VOBSUB,MSGL_ERR,"vobsub_ensure_spu_stream: realloc failure");
return -1;
}
vob->spu_streams = tmp;
@ -438,7 +438,7 @@ vobsub_ensure_spu_stream(vobsub_t *vob, unsigned int index)
else {
vob->spu_streams = malloc((index + 1) * sizeof(packet_queue_t));
if (vob->spu_streams == NULL) {
perror("vobsub_ensure_spu_stream: malloc failure");
mp_msg(MSGT_VOBSUB,MSGL_ERR,"vobsub_ensure_spu_stream: malloc failure");
return -1;
}
}
@ -460,7 +460,7 @@ vobsub_add_id(vobsub_t *vob, const char *id, size_t idlen, const unsigned int in
free(vob->spu_streams[index].id);
vob->spu_streams[index].id = malloc(idlen + 1);
if (vob->spu_streams[index].id == NULL) {
perror("vobsub_add_id: malloc failure");
mp_msg(MSGT_VOBSUB,MSGL_FATAL,"vobsub_add_id: malloc failure");
return -1;
}
vob->spu_streams[index].id[idlen] = 0;
@ -468,7 +468,7 @@ vobsub_add_id(vobsub_t *vob, const char *id, size_t idlen, const unsigned int in
}
vob->spu_streams_current = index;
if (verbose)
fprintf(stderr, "[vobsub] subtitle (vobsubid): %d language %s\n",
mp_msg(MSGT_VOBSUB,MSGL_V,"[vobsub] subtitle (vobsubid): %d language %s\n",
index, vob->spu_streams[index].id);
return 0;
}
@ -479,7 +479,7 @@ vobsub_add_timestamp(vobsub_t *vob, off_t filepos, unsigned int ms)
packet_queue_t *queue;
packet_t *pkt;
if (vob->spu_streams == 0) {
fprintf(stderr, "[vobsub] warning, binning some index entries. Check your index file\n");
mp_msg(MSGT_VOBSUB,MSGL_WARN,"[vobsub] warning, binning some index entries. Check your index file\n");
return -1;
}
queue = vob->spu_streams + vob->spu_streams_current;
@ -676,13 +676,13 @@ vobsub_parse_cuspal(vobsub_t *vob, const char *line)
/* don't know how to use tridx */
static int
vobsub_parse_tridx(vobsub_t *vob, const char *line)
vobsub_parse_tridx(const char *line)
{
//tridx: XXXX
int i;
int tridx;
tridx = strtoul((line + 26), NULL, 16);
tridx = ((tridx&0x1000)>>12) | ((tridx&0x100)>>7) | ((tridx&0x10)>>2) | ((tridx&1)<<3);
return tridx;
}
static int
@ -698,21 +698,21 @@ vobsub_parse_delay(vobsub_t *vob, const char *line)
forward = -1;
line++;
}
fprintf(stderr, "forward=%d", forward);
mp_msg(MSGT_SPUDEC,MSGL_V, "forward=%d", forward);
h = atoi(line + 7);
fprintf(stderr, "h=%d," ,h);
mp_msg(MSGT_VOBSUB,MSGL_V, "h=%d," ,h);
m = atoi(line + 10);
fprintf(stderr, "m=%d,", m);
mp_msg(MSGT_VOBSUB,MSGL_V, "m=%d,", m);
s = atoi(line + 13);
fprintf(stderr, "s=%d,", s);
mp_msg(MSGT_VOBSUB,MSGL_V, "s=%d,", s);
ms = atoi(line + 16);
fprintf(stderr, "ms=%d", ms);
mp_msg(MSGT_VOBSUB,MSGL_V, "ms=%d", ms);
vob->delay = ms + 1000 * (s + 60 * (m + 60 * h)) * forward;
return 0;
}
static int
vobsub_set_lang(vobsub_t *vob, const char *line)
vobsub_set_lang(const char *line)
{
if (vobsub_id == -1)
vobsub_id = atoi(line + 8);
@ -736,7 +736,7 @@ vobsub_parse_one_line(vobsub_t *vob, FILE *fd)
if (*line == 0 || *line == '\r' || *line == '\n' || *line == '#')
continue;
else if (strncmp("langidx:", line, 8) == 0)
res = vobsub_set_lang(vob, line);
res = vobsub_set_lang(line);
else if (strncmp("delay:", line, 6) == 0)
res = vobsub_parse_delay(vob, line);
else if (strncmp("id:", line, 3) == 0)
@ -751,36 +751,37 @@ vobsub_parse_one_line(vobsub_t *vob, FILE *fd)
res = vobsub_parse_timestamp(vob, line + 10);
else if (strncmp("custom colors:", line, 14) == 0)
//custom colors: ON/OFF, tridx: XXXX, colors: XXXXXX, XXXXXX, XXXXXX,XXXXXX
res = vobsub_parse_cuspal(vob, line) + vobsub_parse_tridx(vob, line) + vobsub_parse_custom(vob, line);
res = vobsub_parse_cuspal(vob, line) + vobsub_parse_tridx(line) + vobsub_parse_custom(vob, line);
else {
if (verbose)
fprintf(stderr, "vobsub: ignoring %s", line);
mp_msg(MSGT_VOBSUB,MSGL_V, "vobsub: ignoring %s", line);
continue;
}
if (res < 0)
fprintf(stderr, "ERROR in %s", line);
mp_msg(MSGT_VOBSUB,MSGL_ERR, "ERROR in %s", line);
break;
} while (1);
return res;
}
int
vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force)
vobsub_parse_ifo(void* this, const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force)
{
vobsub_t *vob = (vobsub_t*)this;
int res = -1;
FILE *fd = fopen(name, "rb");
if (fd == NULL) {
if (force)
perror("Can't open IFO file");
mp_msg(MSGT_VOBSUB,MSGL_ERR, "Can't open IFO file");
} else {
// parse IFO header
unsigned char block[0x800];
const char *const ifo_magic = "DVDVIDEO-VTS";
if (fread(block, sizeof(block), 1, fd) != 1) {
if (force)
perror("Can't read IFO header");
mp_msg(MSGT_VOBSUB,MSGL_ERR, "Can't read IFO header");
} else if (memcmp(block, ifo_magic, strlen(ifo_magic) + 1))
fprintf(stderr, "Bad magic in IFO header\n");
mp_msg(MSGT_VOBSUB,MSGL_ERR, "Bad magic in IFO header\n");
else {
unsigned long pgci_sector = block[0xcc] << 24 | block[0xcd] << 16
| block[0xce] << 8 | block[0xcf];
@ -803,11 +804,11 @@ vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *wi
*height /= 2;
break;
default:
fprintf(stderr, "Unknown resolution %d \n", resolution);
mp_msg(MSGT_VOBSUB,MSGL_WARN,"Vobsub: Unknown resolution %d \n", resolution);
}
if (fseek(fd, pgci_sector * sizeof(block), SEEK_SET)
|| fread(block, sizeof(block), 1, fd) != 1)
perror("Can't read IFO PGCI");
mp_msg(MSGT_VOBSUB,MSGL_ERR, "Can't read IFO PGCI");
else {
unsigned long idx;
unsigned long pgc_offset = block[0xc] << 24 | block[0xd] << 16
@ -816,7 +817,8 @@ vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *wi
unsigned char *p = block + pgc_offset + 0xa4 + 4 * idx;
palette[idx] = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}
//vob->have_palette = 1;
if(vob)
vob->have_palette = 1;
res = 0;
}
}
@ -826,12 +828,13 @@ vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *wi
}
void *
vobsub_open(const char *const name, const int force)
vobsub_open(const char *const name,const char *const ifo,const int force,void** spu)
{
vobsub_t *vob = malloc(sizeof(vobsub_t));
if(spu)
*spu = NULL;
if (vob) {
char *buf;
vob->spudec = NULL;
vob->orig_frame_width = 0;
vob->orig_frame_height = 0;
vob->spu_streams = NULL;
@ -843,18 +846,24 @@ vobsub_open(const char *const name, const int force)
FILE *fd;
mpeg_t *mpg;
/* read in the info file */
strcpy(buf, name);
strcat(buf, ".ifo");
vobsub_parse_ifo(buf, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force);
if(!ifo) {
strcpy(buf, name);
strcat(buf, ".ifo");
vobsub_parse_ifo(vob,buf, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force);
} else
vobsub_parse_ifo(vob,ifo, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force);
/* read in the index */
strcpy(buf, name);
strcat(buf, ".idx");
fd = fopen(buf, "rb");
if (fd == NULL) {
if(force)
perror("VobSub: Can't open IDX file");
else
return NULL;
mp_msg(MSGT_VOBSUB,MSGL_ERR,"VobSub: Can't open IDX file");
else {
free(buf);
free(vob);
return NULL;
}
} else {
while (vobsub_parse_one_line(vob, fd) >= 0)
/* NOOP */ ;
@ -863,23 +872,29 @@ vobsub_open(const char *const name, const int force)
/* if no palette in .idx then use custom colors */
if ((vob->custom == 0)&&(vob->have_palette!=1))
vob->custom = 1;
if (vob->orig_frame_width && vob->orig_frame_height)
vob->spudec = spudec_new_scaled_vobsub(vob->palette, vob->cuspal, vob->custom, vob->orig_frame_width, vob->orig_frame_height);
if (spu && vob->orig_frame_width && vob->orig_frame_height)
*spu = spudec_new_scaled_vobsub(vob->palette, vob->cuspal, vob->custom, vob->orig_frame_width, vob->orig_frame_height);
/* read the indexed mpeg_stream */
strcpy(buf, name);
strcat(buf, ".sub");
mpg = mpeg_open(buf);
if (mpg == NULL) {
if(force)
perror("VobSub: Can't open SUB file");
if(force)
mp_msg(MSGT_VOBSUB,MSGL_ERR,"VobSub: Can't open SUB file");
else {
free(buf);
free(vob);
return NULL;
}
} else {
long last_pts_diff = 0;
while (!mpeg_eof(mpg)) {
off_t pos = mpeg_tell(mpg);
if (mpeg_run(mpg) < 0) {
if (!mpeg_eof(mpg))
perror("mpeg_run error");
mp_msg(MSGT_VOBSUB,MSGL_ERR,"mpeg_run error");
break;
}
if (mpg->packet_size) {
@ -912,7 +927,7 @@ vobsub_open(const char *const name, const int force)
}
}
else
fprintf(stderr, "don't know what to do with subtitle #%u\n", sid);
mp_msg(MSGT_VOBSUB,MSGL_WARN, "don't know what to do with subtitle #%u\n", sid);
}
}
}
@ -931,8 +946,6 @@ void
vobsub_close(void *this)
{
vobsub_t *vob = (vobsub_t *)this;
if (vob->spudec)
spudec_free(vob->spudec);
if (vob->spu_streams) {
while (vob->spu_streams_size--)
packet_queue_destroy(vob->spu_streams + vob->spu_streams_size);
@ -941,34 +954,23 @@ vobsub_close(void *this)
free(vob);
}
void vobsub_draw(void *this, int dxs, int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
{
vobsub_t *vob = (vobsub_t *)this;
if (vob->spudec) {
spudec_draw_scaled(vob->spudec, dxs, dys, draw_alpha);
}
}
void
vobsub_process(void *vobhandle, float pts)
{
vobsub_t *vob = (vobsub_t *)vobhandle;
unsigned int pts100 = 90000 * pts;
if (vob->spudec) {
spudec_heartbeat(vob->spudec, pts100);
if (vob->spu_streams && 0 <= vobsub_id && (unsigned) vobsub_id < vob->spu_streams_size) {
packet_queue_t *queue = vob->spu_streams + vobsub_id;
while (queue->current_index < queue->packets_size) {
packet_t *pkt = queue->packets + queue->current_index;
if (pkt->pts100 <= pts100) {
spudec_assemble(vob->spudec, pkt->data, pkt->size, pkt->pts100);
++queue->current_index;
}
else
break;
}
}
int
vobsub_get_packet(void *vobhandle, float pts,void** data, int* timestamp) {
vobsub_t *vob = (vobsub_t *)vobhandle;
unsigned int pts100 = 90000 * pts;
if (vob->spu_streams && 0 <= vobsub_id && (unsigned) vobsub_id < vob->spu_streams_size) {
packet_queue_t *queue = vob->spu_streams + vobsub_id;
while (queue->current_index < queue->packets_size) {
packet_t *pkt = queue->packets + queue->current_index;
if (pkt->pts100 <= pts100) {
++queue->current_index;
*data = pkt->data;
*timestamp = pkt->pts100;
return pkt->size;
} else break;
}
}
return -1;
}
void
@ -980,6 +982,4 @@ vobsub_reset(void *vobhandle)
while (n-- > 0)
vob->spu_streams[n].current_index = 0;
}
if (vob->spudec)
spudec_reset(vob->spudec);
}

View File

@ -1,10 +1,10 @@
#ifndef MPLAYER_VOBSUB_H
#define MPLAYER_VOBSUB_H
extern void *vobsub_open(const char *subname, const int force);
extern void vobsub_process(void *vob, float pts);
extern void *vobsub_open(const char *subname, const char *const ifo, const int force, void** spu);
extern void vobsub_reset(void *vob);
extern void vobsub_draw(void *vob, int dxs, int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
extern int vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force);
extern int vobsub_parse_ifo(void* this, const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force);
extern int vobsub_get_packet(void *vobhandle, float pts,void** data, int* timestamp);
extern void vobsub_close(void *this);
#endif /* MPLAYER_VOBSUB_H */