mirror of
https://github.com/mpv-player/mpv
synced 2024-12-24 07:33:46 +01:00
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.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6675 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
6e7e73bc90
commit
f1a69972e9
@ -114,6 +114,10 @@ static config_t mencoder_opts[]={
|
||||
{"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
|
||||
|
50
mencoder.c
50
mencoder.c
@ -144,6 +144,10 @@ static int skip_limit=-1;
|
||||
|
||||
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_audio_t *sh_audio=NULL;
|
||||
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 @@ if(sh_audio && (out_audio_codec || seek_to_sec || !sh_audio->wf)){
|
||||
|
||||
// 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 @@ vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream-
|
||||
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 @@ if(sh_audio && !demuxer2){
|
||||
|
||||
#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 @@ if(ferror(muxer_f) || fclose(muxer_f) != 0) {
|
||||
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));
|
||||
|
@ -1171,7 +1171,7 @@ 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(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);
|
||||
}
|
||||
|
||||
|
162
vobsub.c
162
vobsub.c
@ -14,6 +14,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "stream.h"
|
||||
#include "vobsub.h"
|
||||
@ -229,7 +230,7 @@ mpeg_run(mpeg_t *mpeg)
|
||||
}
|
||||
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 @@ packet_queue_insert(packet_queue_t *queue)
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Vosub
|
||||
* Vobsub
|
||||
**********************************************************************/
|
||||
|
||||
typedef struct {
|
||||
@ -765,7 +766,8 @@ vobsub_parse_one_line(vobsub_t *vob, FILE *fd)
|
||||
}
|
||||
|
||||
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 @@ vobsub_parse_ifo(void* this, const char *const name, unsigned int *palette, unsi
|
||||
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 @@ vobsub_open(const char *const name,const char *const ifo,const int force,void**
|
||||
*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 @@ vobsub_open(const char *const name,const char *const ifo,const int force,void**
|
||||
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 @@ vobsub_open(const char *const name,const char *const ifo,const int force,void**
|
||||
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 @@ vobsub_reset(void *vobhandle)
|
||||
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 <URL:http://www.mplayerhq.hu/> for more information about MPlayer\n"
|
||||
"# See <URL:http://vobsub.edensrising.com/> 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");
|
||||
}
|
||||
}
|
||||
|
||||
|
7
vobsub.h
7
vobsub.h
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user