# HG changeset patch # User atmos4 # Date 1026164691 0 # Node ID f8551f89dd48c06b275dda40d9c87f64746e5bcc # Parent d6adae1af0e330dcb4db73321af67a0188c3978b MEncoder vobsub ripping support, currently not compatible with windows vobsub, some bugs to be fixed. However it already works with mplayer, so it's a start. diff -r d6adae1af0e3 -r f8551f89dd48 cfg-mencoder.h --- a/cfg-mencoder.h Mon Jul 08 21:34:24 2002 +0000 +++ b/cfg-mencoder.h Mon Jul 08 21:44:51 2002 +0000 @@ -114,6 +114,10 @@ {"pass", &pass, CONF_TYPE_INT, CONF_RANGE,0,2, NULL}, {"passlogfile", &passtmpfile, CONF_TYPE_STRING, 0, 0, 0, NULL}, + {"vobsubout", &vobsub_out, CONF_TYPE_STRING, 0, 0, 0, NULL}, + {"vobsuboutindex", &vobsub_out_index, CONF_TYPE_INT, CONF_RANGE, 0, 31, NULL}, + {"vobsuboutid", &vobsub_out_id, CONF_TYPE_STRING, 0, 0, 0, NULL}, + #ifdef HAVE_DIVX4ENCORE {"divx4opts", divx4opts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL}, #endif diff -r d6adae1af0e3 -r f8551f89dd48 mencoder.c --- a/mencoder.c Mon Jul 08 21:34:24 2002 +0000 +++ b/mencoder.c Mon Jul 08 21:44:51 2002 +0000 @@ -144,6 +144,10 @@ int force_srate=0; +char *vobsub_out=NULL; +unsigned int vobsub_out_index=0; +char *vobsub_out_id=NULL; + char* out_filename="test.avi"; char *force_fourcc=NULL; @@ -306,6 +310,9 @@ sh_video_t *sh_video=NULL; int file_format=DEMUXER_TYPE_UNKNOWN; int i; +void *vobsub_writer=NULL; +double vobsubout_origin_pts=0.0; +int vobsubout_origin_pts_set=0; uint32_t ptimer_start; uint32_t audiorate=0; @@ -509,9 +516,36 @@ // set up video encoder: +if (vobsub_out) { + unsigned int palette[16], width, height; + unsigned char tmp[3] = { 0, 0, 0 }; + if (spudec_ifo && vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1, dvdsub_id, tmp) >= 0) + vobsub_writer = vobsub_out_open(vobsub_out, palette, sh_video->disp_w, sh_video->disp_h, + vobsub_out_id?vobsub_out_id:tmp, vobsub_out_index); +#ifdef USE_DVDREAD + if (vobsub_writer == NULL) { + char tmp[3]; + if (vobsub_out_id == NULL && stream->type == STREAMTYPE_DVD) { + int i; + dvd_priv_t *dvd = (dvd_priv_t*)stream->priv; + for (i = 0; i < dvd->nr_of_subtitles; ++i) + if (dvd->subtitles[i].id == dvdsub_id) { + tmp[0] = (dvd->subtitles[i].language >> 8) & 0xff; + tmp[1] = dvd->subtitles[i].language & 0xff; + tmp[2] = 0; + vobsub_out_id = tmp; + break; + } + } + vobsub_writer=vobsub_out_open(vobsub_out, stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL, + sh_video->disp_w, sh_video->disp_h, vobsub_out_id, vobsub_out_index); + } +#endif +} +else { if (spudec_ifo) { unsigned int palette[16], width, height; - if (vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1) >= 0) + if (vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1, -1, NULL) >= 0) vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h); } #ifdef USE_DVDREAD @@ -520,6 +554,7 @@ sh_video->disp_w, sh_video->disp_h); } #endif +} #ifdef USE_SUB // after reading video params we should load subtitles because @@ -1113,15 +1148,24 @@ #ifdef USE_DVDREAD // DVD sub: - if(vo_spudec){ + if(vo_spudec||vobsub_writer){ unsigned char* packet=NULL; int len; + if (vobsub_writer && !vobsubout_origin_pts_set) { + vobsubout_origin_pts_set = 1; + vobsubout_origin_pts = d_video->pts; + } while((len=ds_get_packet_sub(d_dvdsub,&packet))>0){ mp_msg(MSGT_MENCODER,MSGL_V,"\rDVD sub: len=%d v_pts=%5.3f s_pts=%5.3f \n",len,d_video->pts,d_dvdsub->pts); + if (vo_spudec) spudec_assemble(vo_spudec,packet,len,90000*d_dvdsub->pts); + if (vobsub_writer) + vobsub_out_output(vobsub_writer,packet,len,d_dvdsub->pts-vobsubout_origin_pts); } + if (vo_spudec) { spudec_heartbeat(vo_spudec,90000*d_video->pts); vo_osd_changed(OSDTYPE_SPU); + } } #endif @@ -1157,6 +1201,8 @@ mp_msg(MSGT_MENCODER,MSGL_FATAL,"%s: error writing file.\n", out_filename); mencoder_exit(1, NULL); } +if(vobsub_writer) + vobsub_out_close(vobsub_writer); if(out_video_codec==VCODEC_FRAMENO && mux_v->timer>100){ printf("Recommended video bitrate for 650MB CD: %d\n",(int)((650*1024*1024-muxer_f_size)/mux_v->timer/125)); diff -r d6adae1af0e3 -r f8551f89dd48 mplayer.c --- a/mplayer.c Mon Jul 08 21:34:24 2002 +0000 +++ b/mplayer.c Mon Jul 08 21:44:51 2002 +0000 @@ -1171,7 +1171,7 @@ if (spudec_ifo) { unsigned int palette[16], width, height; current_module="spudec_init_vobsub"; - if (vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1) >= 0) + if (vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1, -1, NULL) >= 0) vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h); } diff -r d6adae1af0e3 -r f8551f89dd48 vobsub.c --- a/vobsub.c Mon Jul 08 21:34:24 2002 +0000 +++ b/vobsub.c Mon Jul 08 21:44:51 2002 +0000 @@ -14,6 +14,7 @@ #include #include "config.h" +#include "version.h" #include "stream.h" #include "vobsub.h" @@ -229,7 +230,7 @@ } else mpeg->pts = ((buf[0] & 0x0e) << 29 | buf[1] << 22 | (buf[2] & 0xfe) << 14 - | buf[3] << 7 | (buf[4] >> 1)) / 900; + | buf[3] << 7 | (buf[4] >> 1)); } else /* if ((pts_flags & 0xc0) == 0xc0) */ { /* what's this? */ @@ -404,7 +405,7 @@ } /********************************************************************** - * Vosub + * Vobsub **********************************************************************/ typedef struct { @@ -765,7 +766,8 @@ } int -vobsub_parse_ifo(void* this, 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, + int sid, char *langid) { vobsub_t *vob = (vobsub_t*)this; int res = -1; @@ -806,6 +808,12 @@ default: mp_msg(MSGT_VOBSUB,MSGL_WARN,"Vobsub: Unknown resolution %d \n", resolution); } + if (langid && 0 <= sid && sid < 32) { + unsigned char *tmp = block + 0x256 + sid * 6 + 2; + langid[0] = tmp[0]; + langid[1] = tmp[1]; + langid[2] = 0; + } if (fseek(fd, pgci_sector * sizeof(block), SEEK_SET) || fread(block, sizeof(block), 1, fd) != 1) mp_msg(MSGT_VOBSUB,MSGL_ERR, "Can't read IFO PGCI"); @@ -835,6 +843,8 @@ *spu = NULL; if (vob) { char *buf; + vob->custom = 0; + vob->have_palette = 0; vob->orig_frame_width = 0; vob->orig_frame_height = 0; vob->spu_streams = NULL; @@ -849,9 +859,9 @@ if(!ifo) { strcpy(buf, name); strcat(buf, ".ifo"); - vobsub_parse_ifo(vob,buf, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force); + vobsub_parse_ifo(vob,buf, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force, -1, NULL); } else - vobsub_parse_ifo(vob,ifo, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force); + vobsub_parse_ifo(vob,ifo, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force, -1, NULL); /* read in the index */ strcpy(buf, name); strcat(buf, ".idx"); @@ -917,7 +927,10 @@ mpg->pts + last_pts_diff; } pkt = queue->packets + queue->current_index; - last_pts_diff = pkt->pts100 - mpg->pts; + if (queue->packets_size > 1) + last_pts_diff = pkt->pts100 - mpg->pts; + else + pkt->pts100 = mpg->pts; /* FIXME: should not use mpg_sub internal informations, make a copy */ pkt->data = mpg->packet; pkt->size = mpg->packet_size; @@ -983,3 +996,140 @@ vob->spu_streams[n].current_index = 0; } } + +/********************************************************************** + * Vobsub output + **********************************************************************/ + +typedef struct { + FILE *fsub; + FILE *fidx; + unsigned int aid; +} vobsub_out_t; + +static void +create_idx(vobsub_out_t *me, const unsigned int *palette, unsigned int orig_width, unsigned int orig_height) +{ + int i; + fprintf(me->fidx, + "# VobSub index file, v3 (do not modify this line!)\n" + "#\n" + "# Generated by MPlayer " VERSION "\n" + "# See for more information about MPlayer\n" + "# See for more information about Vobsub\n" + "#\n" + "size: %ux%u\n", + orig_width, orig_height); + if (palette) { + fputs("palette:", me->fidx); + for (i = 0; i < 16; ++i) { + if (i) + putc(',', me->fidx); + fprintf(me->fidx, " %06x", palette[i] & 0x00ffffff); + } + putc('\n', me->fidx); + } +} + +void * +vobsub_out_open(const char *basename, const unsigned int *palette, + unsigned int orig_width, unsigned int orig_height, + const char *id, unsigned int index) +{ + vobsub_out_t *result = NULL; + char *filename; + filename = malloc(strlen(basename) + 5); + if (filename) { + result = malloc(sizeof(vobsub_out_t)); + result->fsub = NULL; + result->fidx = NULL; + result->aid = 0; + if (result) { + result->aid = index; + strcpy(filename, basename); + strcat(filename, ".sub"); + result->fsub = fopen(filename, "a"); + if (result->fsub == NULL) + perror("Error: vobsub_out_open subtitle file open failed"); + strcpy(filename, basename); + strcat(filename, ".idx"); + result->fidx = fopen(filename, "a"); + if (result->fidx) { + setvbuf(result->fidx, NULL, _IOLBF, 0); + if (ftell(result->fidx) == 0) + create_idx(result, palette, orig_width, orig_height); + fprintf(result->fidx, "\nid: %s, index: %u\n", id ? id : "xx", index); + } + else + perror("Error: vobsub_out_open index file open failed"); + free(filename); + } + } + return result; +} + +void +vobsub_out_close(void *me) +{ + vobsub_out_t *vob = (vobsub_out_t*)me; + if (vob->fidx) + fclose(vob->fidx); + if (vob->fsub) + fclose(vob->fsub); + free(vob); +} + +void +vobsub_out_output(void *me, const unsigned char *packet, int len, double pts) +{ + vobsub_out_t *vob = (vobsub_out_t*)me; + if (vob->fsub) { + unsigned char buffer[2048]; + if (vob->fidx) { + unsigned int h, m, ms; + double s; + s = pts; + h = s / 3600; + s -= h * 3600; + m = s / 60; + s -= m * 60; + ms = (s - (unsigned int) s) * 1000; + if (ms >= 1000) /* prevent overfolws or bad float stuff */ + ms = 0; + fprintf(vob->fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09lx\n", + h, m, (unsigned int) s, ms, ftell(vob->fsub)); + } + buffer[0] = 0; + buffer[1] = 0; + buffer[2] = 1; + buffer[3] = 0xbd; + buffer[4] = ((9 + len) >> 8) & 0xff; /* length of payload */ + buffer[5] = (9 + len) & 0xff; + buffer[6] = 0x80; /* System-2 (.VOB) stream */ + buffer[7] = 0x80; /* pts_flags */ + buffer[8] = 5; /* hdrlen */ + pts *= 90000; + buffer[9] = 0x21 | (((unsigned long)pts >> 29) & 0x0e); + buffer[10] = ((unsigned long)pts >> 22) & 0xff; + buffer[11] = 0x01 | (((unsigned long)pts >> 14) & 0xfe); + buffer[12] = ((unsigned long)pts >> 7) & 0xff; + buffer[13] = 0x01 | (((unsigned long)pts << 1) & 0xfe); + buffer[14] = 0x20 | vob->aid; /* aid */ + if (fwrite(buffer, 15, 1, vob->fsub) != 1 + || fwrite(packet, len, 1, vob->fsub) != 1) + perror("ERROR: vobsub write failed"); + /* padding */ + len = 2048 - 15 - len; + buffer[0] = 0x00; + buffer[1] = 0x00; + buffer[2] = 0x01; + buffer[3] = 0xbe; + buffer[4] = (len - 6) >> 8; + buffer[5] = (len - 6) & 0xff; + /* for better compression, blank this */ + memset(buffer + 6, 0, len - 6); + if (fwrite(buffer, len, 1, vob->fsub) != 1) + perror("ERROR: vobsub padding write failed"); + } +} + diff -r d6adae1af0e3 -r f8551f89dd48 vobsub.h --- a/vobsub.h Mon Jul 08 21:34:24 2002 +0000 +++ b/vobsub.h Mon Jul 08 21:44:51 2002 +0000 @@ -3,8 +3,13 @@ extern void *vobsub_open(const char *subname, const char *const ifo, const int force, void** spu); extern void vobsub_reset(void *vob); -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_parse_ifo(void* this, const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force, int sid, char *langid); extern int vobsub_get_packet(void *vobhandle, float pts,void** data, int* timestamp); extern void vobsub_close(void *this); +extern void *vobsub_out_open(const char *basename, const unsigned int *palette, unsigned int orig_width, unsigned int orig_height, const char *id, unsigned int index); +extern void vobsub_out_output(void *me, const unsigned char *packet, int len, double pts); +extern void vobsub_out_close(void *me); + #endif /* MPLAYER_VOBSUB_H */ +