⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vobsub.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 3 页
字号:
		*width = 704;		break;	    case 0x2:		*width = 352;		break;	    case 0x3:		*width = 352;		*height /= 2;		break;	    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 (rar_seek(fd, pgci_sector * sizeof(block), SEEK_SET)		|| rar_read(block, sizeof(block), 1, fd) != 1)		mp_msg(MSGT_VOBSUB,MSGL_ERR, "VobSub: Can't read IFO PGCI\n");	    else {		unsigned long idx;		unsigned long pgc_offset = block[0xc] << 24 | block[0xd] << 16		    | block[0xe] << 8 | block[0xf];		for (idx = 0; idx < 16; ++idx) {		    unsigned char *p = block + pgc_offset + 0xa4 + 4 * idx;		    palette[idx] = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];		}		if(vob)		  vob->have_palette = 1;		res = 0;	    }	}	rar_close(fd);    }    return res;}void *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->custom = 0;	vob->have_palette = 0;	vob->orig_frame_width = 0;	vob->orig_frame_height = 0;	vob->spu_streams = NULL;	vob->spu_streams_size = 0;	vob->spu_streams_current = 0;	vob->delay = 0;	vob->forced_subs=0;	buf = malloc((strlen(name) + 5) * sizeof(char));	if (buf) {	    rar_stream_t *fd;	    mpeg_t *mpg;	    /* read in the info file */	    if(!ifo) {	      strcpy(buf, name);	      strcat(buf, ".ifo");	      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, -1, NULL);	    /* read in the index */	    strcpy(buf, name);	    strcat(buf, ".idx");	    fd = rar_open(buf, "rb");	    if (fd == NULL) {		if(force)		  mp_msg(MSGT_VOBSUB,MSGL_ERR,"VobSub: Can't open IDX file\n");		else {		  free(buf);		  free(vob);		  return NULL;		}	    } else {		while (vobsub_parse_one_line(vob, fd) >= 0)		    /* NOOP */ ;		rar_close(fd);	    }	    /* if no palette in .idx then use custom colors */	    if ((vob->custom == 0)&&(vob->have_palette!=1))		vob->custom = 1;	    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)		mp_msg(MSGT_VOBSUB,MSGL_ERR,"VobSub: Can't open SUB file\n");	      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))			    mp_msg(MSGT_VOBSUB,MSGL_ERR,"VobSub: mpeg_run error\n");			break;		    }		    if (mpg->packet_size) {			if ((mpg->aid & 0xe0) == 0x20) {			    unsigned int sid = mpg->aid & 0x1f;			    if (vobsub_ensure_spu_stream(vob, sid) >= 0)  {				packet_queue_t *queue = vob->spu_streams + sid;				/* get the packet to fill */				if (queue->packets_size == 0 && packet_queue_grow(queue)  < 0)				  abort();				while (queue->current_index + 1 < queue->packets_size				       && queue->packets[queue->current_index + 1].filepos <= pos)				    ++queue->current_index;				if (queue->current_index < queue->packets_size) {				    packet_t *pkt;				    if (queue->packets[queue->current_index].data) {					/* insert a new packet and fix the PTS ! */					packet_queue_insert(queue);					queue->packets[queue->current_index].pts100 =					    mpg->pts + last_pts_diff;				    }				    pkt = queue->packets + queue->current_index;				    if (pkt->pts100 != UINT_MAX) {				    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;				    mpg->packet = NULL;				    mpg->packet_reserve = 0;				    mpg->packet_size = 0;				    }				}			    }			    else				mp_msg(MSGT_VOBSUB,MSGL_WARN, "don't know what to do with subtitle #%u\n", sid);			}		    }		}		vob->spu_streams_current = vob->spu_streams_size;		while (vob->spu_streams_current-- > 0)		    vob->spu_streams[vob->spu_streams_current].current_index = 0;		mpeg_free(mpg);	    }	    free(buf);	}    }    return vob;}voidvobsub_close(void *this){    vobsub_t *vob = (vobsub_t *)this;    if (vob->spu_streams) {	while (vob->spu_streams_size--)	    packet_queue_destroy(vob->spu_streams + vob->spu_streams_size);	free(vob->spu_streams);    }    free(vob);}unsigned intvobsub_get_indexes_count(void *vobhandle){    vobsub_t *vob = (vobsub_t *) vobhandle;    return vob->spu_streams_size;}char *vobsub_get_id(void *vobhandle, unsigned int index){    vobsub_t *vob = (vobsub_t *) vobhandle;    return (index < vob->spu_streams_size) ? vob->spu_streams[index].id : NULL;}unsigned int vobsub_get_forced_subs_flag(void const * const vobhandle){  if (vobhandle)    return ((vobsub_t*) vobhandle)->forced_subs;  else    return 0;}intvobsub_set_from_lang(void *vobhandle, unsigned char * lang){    int i;    vobsub_t *vob= (vobsub_t *) vobhandle;    while(lang && strlen(lang) >= 2){      for(i=0; i < vob->spu_streams_size; i++)        if (vob->spu_streams[i].id)          if ((strncmp(vob->spu_streams[i].id, lang, 2)==0)){	    vobsub_id=i;	    mp_msg(MSGT_VOBSUB, MSGL_INFO, "Selected VOBSUB language: %d language: %s\n", i, vob->spu_streams[i].id);	    return 0;	  }      lang+=2;while (lang[0]==',' || lang[0]==' ') ++lang;    }    mp_msg(MSGT_VOBSUB, MSGL_WARN, "No matching VOBSUB language found!\n");    return -1;}    intvobsub_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 != UINT_MAX)      if (pkt->pts100 <= pts100) {	++queue->current_index;	*data = pkt->data;	*timestamp = pkt->pts100;	return pkt->size;      } else break;      else	  ++queue->current_index;    }  }  return -1;}intvobsub_get_next_packet(void *vobhandle, void** data, int* timestamp){  vobsub_t *vob = (vobsub_t *)vobhandle;  if (vob->spu_streams && 0 <= vobsub_id && (unsigned) vobsub_id < vob->spu_streams_size) {    packet_queue_t *queue = vob->spu_streams + vobsub_id;    if (queue->current_index < queue->packets_size) {      packet_t *pkt = queue->packets + queue->current_index;      ++queue->current_index;      *data = pkt->data;      *timestamp = pkt->pts100;      return pkt->size;    }  }  return -1;}void vobsub_seek(void * vobhandle, float pts){  vobsub_t * vob = (vobsub_t *)vobhandle;  packet_queue_t * queue;  int seek_pts100 = (int)pts * 90000;  if (vob->spu_streams && 0 <= vobsub_id && (unsigned) vobsub_id < vob->spu_streams_size) {    /* do not seek if we don't know the id */    if (vobsub_get_id(vob, vobsub_id) == NULL)	    return;    queue = vob->spu_streams + vobsub_id;    queue->current_index = 0;    while ((queue->packets + queue->current_index)->pts100 < seek_pts100)      ++queue->current_index;    if (queue->current_index > 0)      --queue->current_index;  }}voidvobsub_reset(void *vobhandle){    vobsub_t *vob = (vobsub_t *)vobhandle;    if (vob->spu_streams) {	unsigned int n = vob->spu_streams_size;	while (n-- > 0)	    vob->spu_streams[n].current_index = 0;    }}/********************************************************************** * Vobsub output **********************************************************************/typedef struct {    FILE *fsub;    FILE *fidx;    unsigned int aid;} vobsub_out_t;static voidcreate_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, v7 (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) {	    const double y = palette[i] >> 16 & 0xff,		u = (palette[i] >> 8 & 0xff) - 128.0,		v = (palette[i] & 0xff) - 128.0;	    if (i)		putc(',', me->fidx);	    fprintf(me->fidx, " %02x%02x%02x",		    MIN(MAX((int)(y + 1.4022 * u), 0), 0xff),		    MIN(MAX((int)(y - 0.3456 * u - 0.7145 * v), 0), 0xff),		    MIN(MAX((int)(y + 1.7710 * v), 0), 0xff));	}	putc('\n', me->fidx);    }    fprintf(me->fidx,"# ON: displays only forced subtitles, OFF: shows everything\n"	    "forced subs: OFF\n");}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) {		if (ftell(result->fidx) == 0){		    create_idx(result, palette, orig_width, orig_height);                    /* Make the selected language the default language */                    fprintf(result->fidx, "\n# Language index in use\nlangidx: %u\n", index);		}		fprintf(result->fidx, "\nid: %s, index: %u\n", id ? id : "xx", index);		/* So that we can check the file now */		fflush(result->fidx);	    }	    else		perror("Error: vobsub_out_open index file open failed");	    free(filename);	}    }    return result;}voidvobsub_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);}voidvobsub_out_output(void *me, const unsigned char *packet, int len, double pts){    static double last_pts;    static int last_pts_set = 0;    vobsub_out_t *vob = (vobsub_out_t*)me;    if (vob->fsub) {	/*  Windows' Vobsub require that every packet is exactly 2kB long */	unsigned char buffer[2048];	unsigned char *p;	int remain = 2048;	/* Do not output twice a line with the same timestamp, this	   breaks Windows' Vobsub */	if (vob->fidx && (!last_pts_set || last_pts != pts)) {	    static unsigned int last_h = 9999, last_m = 9999, last_s = 9999, last_ms = 9999;	    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;	    if (h != last_h || m != last_m || (unsigned int) s != last_s || ms != last_ms) {		fprintf(vob->fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09lx\n",			h, m, (unsigned int) s, ms, ftell(vob->fsub));		last_h = h;		last_m = m;		last_s = (unsigned int) s;		last_ms = ms;	    }	}	last_pts = pts;	last_pts_set = 1;	/* Packet start code: Windows' Vobsub needs this */ 	p = buffer;	*p++ = 0;		/* 0x00 */	*p++ = 0;	*p++ = 1;	*p++ = 0xba;	*p++ = 0x40;	memset(p, 0, 9);	p += 9;	{   /* Packet */	    static unsigned char last_pts[5] = { 0, 0, 0, 0, 0};	    unsigned char now_pts[5];	    int pts_len, pad_len, datalen = len;	    pts *= 90000;	    now_pts[0] = 0x21 | (((unsigned long)pts >> 29) & 0x0e);	    now_pts[1] = ((unsigned long)pts >> 22) & 0xff;	    now_pts[2] = 0x01 | (((unsigned long)pts >> 14) & 0xfe);	    now_pts[3] = ((unsigned long)pts >> 7) & 0xff;	    now_pts[4] = 0x01 | (((unsigned long)pts << 1) & 0xfe);	    pts_len = memcmp(last_pts, now_pts, sizeof(now_pts)) ? sizeof(now_pts) : 0;	    memcpy(last_pts, now_pts, sizeof(now_pts));	    datalen += 3;	/* Version, PTS_flags, pts_len */	    datalen += pts_len;	    datalen += 1;	/* AID */	    pad_len = 2048 - (p - buffer) - 4 /* MPEG ID */ - 2 /* payload len */ - datalen;	    /* XXX - Go figure what should go here!  In any case the	       packet has to be completly filled.  If I can fill it	       with padding (0x000001be) latter I'll do that.  But if	       there is only room for 6 bytes then I can not write a	       padding packet.  So I add some padding in the PTS	       field.  This looks like a dirty kludge.  Oh well... */	    if (pad_len < 0) {		/* Packet is too big.  Let's try ommiting the PTS field */		datalen -= pts_len;		pts_len = 0;		pad_len = 0;	    }	    else if (pad_len > 6)		pad_len = 0;	    datalen += pad_len;	    *p++ = 0;		/* 0x0e */	    *p++ = 0;	    *p++ = 1;	    *p++ = 0xbd;	    *p++ = (datalen >> 8) & 0xff; /* length of payload */	    *p++ = datalen & 0xff;	    *p++ = 0x80;		/* System-2 (.VOB) stream */	    *p++ = pts_len ? 0x80 : 0x00; /* pts_flags */	    *p++ = pts_len + pad_len;	    memcpy(p, now_pts, pts_len);	    p += pts_len;	    memset(p, 0, pad_len);	    p += pad_len;	}	*p++ = 0x20 |  vob->aid; /* aid */	if (fwrite(buffer, p - buffer, 1, vob->fsub) != 1	    || fwrite(packet, len, 1, vob->fsub) != 1)	    perror("ERROR: vobsub write failed");	else	    remain -= p - buffer + len;	/* Padding */	if (remain >= 6) {	    p = buffer;	    *p++ = 0x00;	    *p++ = 0x00;	    *p++ = 0x01;	    *p++ = 0xbe;	    *p++ = (remain - 6) >> 8;	    *p++ = (remain - 6) & 0xff;	    /* for better compression, blank this */	    memset(buffer + 6, 0, remain - (p - buffer));	    if (fwrite(buffer, remain, 1, vob->fsub) != 1)		perror("ERROR: vobsub padding write failed");	}	else if (remain > 0) {	    /* I don't know what to output.  But anyway the block	       needs to be 2KB big */	    memset(buffer, 0, remain);	    if (fwrite(buffer, remain, 1, vob->fsub) != 1)		perror("ERROR: vobsub blank padding write failed");	}	else if (remain < 0)	    fprintf(stderr,		    "\nERROR: wrong thing happenned...\n"		    "  I wrote a %i data bytes spu packet and that's too long\n", len);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -