diff --git a/libvo/sub.c b/libvo/sub.c index 00780cf7ce..5e44238121 100644 --- a/libvo/sub.c +++ b/libvo/sub.c @@ -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; diff --git a/libvo/sub.h b/libvo/sub.h index 21482eea80..c15a2a99d0 100644 --- a/libvo/sub.h +++ b/libvo/sub.h @@ -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 diff --git a/libvo/video_out.h b/libvo/video_out.h index 62b20a3a60..1490048c72 100644 --- a/libvo/video_out.h +++ b/libvo/video_out.h @@ -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 diff --git a/mencoder.c b/mencoder.c index 3efac12a0d..a5440f28c1 100644 --- a/mencoder.c +++ b/mencoder.c @@ -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 diff --git a/mp_msg.h b/mp_msg.h index 1809455a13..db149c64f8 100644 --- a/mp_msg.h +++ b/mp_msg.h @@ -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(); diff --git a/mplayer.c b/mplayer.c index 9b9c38afa2..e670d24e07 100644 --- a/mplayer.c +++ b/mplayer.c @@ -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,×tamp); + 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) diff --git a/spudec.c b/spudec.c index 58cfba0443..887bb37a3e 100644 --- a/spudec.c +++ b/spudec.c @@ -29,6 +29,7 @@ #if ANTIALIASING_ALGORITHM == 2 #include #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); +} diff --git a/spudec.h b/spudec.h index 81ce6013da..5cea2330df 100644 --- a/spudec.h +++ b/spudec.h @@ -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 diff --git a/vobsub.c b/vobsub.c index 138cbf0071..2f90338938 100644 --- a/vobsub.c +++ b/vobsub.c @@ -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); } diff --git a/vobsub.h b/vobsub.h index a5700c06b3..a1b713d8e5 100644 --- a/vobsub.h +++ b/vobsub.h @@ -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 */