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

📄 vobsub.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Some code freely inspired from VobSub <URL:http://vobsub.edensrising.com>, * with kind permission from Gabest <gabest@freemail.hu> */#include <ctype.h>#include <errno.h>#include <limits.h>#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include "config.h"#include "version.h"#include "vobsub.h"#include "spudec.h"#include "mp_msg.h"#ifdef USE_UNRARLIB#include "unrarlib.h"#endif#define MIN(a, b)	((a)<(b)?(a):(b))#define MAX(a, b)	((a)>(b)?(a):(b))extern int vobsub_id;/********************************************************************** * RAR stream handling * The RAR file must have the same basename as the file to open * See <URL:http://www.unrarlib.org/> **********************************************************************/#ifdef USE_UNRARLIBtypedef struct {    FILE *file;    unsigned char *data;    unsigned long size;    unsigned long pos;} rar_stream_t;static rar_stream_t *rar_open(const char *const filename, const char *const mode){    rar_stream_t *stream;    /* unrarlib can only read */    if (strcmp("r", mode) && strcmp("rb", mode)) {	errno = EINVAL;	return NULL;    }    stream = malloc(sizeof(rar_stream_t));    if (stream == NULL)	return NULL;    /* first try normal access */    stream->file = fopen(filename, mode);    if (stream->file == NULL) {	char *rar_filename;	const char *p;	int rc;	/* Guess the RAR archive filename */	rar_filename = NULL;	p = strrchr(filename, '.');	if (p) {	    ptrdiff_t l = p - filename;	    rar_filename = malloc(l + 5);	    if (rar_filename == NULL) {		free(stream);		return NULL;	    }	    strncpy(rar_filename, filename, l);	    strcpy(rar_filename + l, ".rar");	}	else {	    rar_filename = malloc(strlen(filename) + 5);	    if (rar_filename == NULL) {		free(stream);		return NULL;	    }	    strcpy(rar_filename, filename);	    strcat(rar_filename, ".rar");	}	/* get rid of the path if there is any */	if ((p = strrchr(filename, '/')) == NULL) {		p = filename;	} else {		p++;	}	rc = urarlib_get(&stream->data, &stream->size, (char*) p, rar_filename, "");	if (!rc) {	    /* There is no matching filename in the archive. However, sometimes	     * the files we are looking for have been given arbitrary names in the archive.	     * Let's look for a file with an exact match in the extension only. */	    int i, num_files, name_len;	    ArchiveList_struct *list, *lp;	    /* the cast in the next line is a hack to overcome a design flaw (IMHO) in unrarlib */	    num_files = urarlib_list (rar_filename, (ArchiveList_struct *)&list);	    if (num_files > 0) {		char *demanded_ext;		demanded_ext = strrchr (p, '.');		if (demanded_ext) {		    int demanded_ext_len = strlen (demanded_ext);	    	    for (i=0, lp=list; i<num_files; i++, lp=lp->next) {			name_len = strlen (lp->item.Name);			if (name_len >= demanded_ext_len && !strcasecmp (lp->item.Name + name_len - demanded_ext_len, demanded_ext)) {		            if ((rc = urarlib_get(&stream->data, &stream->size, lp->item.Name, rar_filename, ""))) {				break;		   	    }			}		    }		}	    	urarlib_freelist (list);	    }	    if (!rc) {		free(rar_filename);		free(stream);		return NULL;	    }	}	free(rar_filename);	stream->pos = 0;    }    return stream;}static intrar_close(rar_stream_t *stream){    if (stream->file)	return fclose(stream->file);    free(stream->data);    return 0;}static intrar_eof(rar_stream_t *stream){    if (stream->file)	return feof(stream->file);    return stream->pos >= stream->size;}static longrar_tell(rar_stream_t *stream){    if (stream->file)	return ftell(stream->file);    return stream->pos;}static intrar_seek(rar_stream_t *stream, long offset, int whence){    if (stream->file)	return fseek(stream->file, offset, whence);    switch (whence) {    case SEEK_SET:	if (offset < 0) {	    errno = EINVAL;	    return -1;	}	stream->pos = offset;	break;    case SEEK_CUR:	if (offset < 0 && stream->pos < (unsigned long) -offset) {	    errno = EINVAL;	    return -1;	}	stream->pos += offset;	break;    case SEEK_END:	if (offset < 0 && stream->size < (unsigned long) -offset) {	    errno = EINVAL;	    return -1;	}	stream->pos = stream->size + offset;	break;    default:	errno = EINVAL;	return -1;    }    return 0;}static intrar_getc(rar_stream_t *stream){    if (stream->file)	return getc(stream->file);    if (rar_eof(stream))	return EOF;    return stream->data[stream->pos++];}static size_trar_read(void *ptr, size_t size, size_t nmemb, rar_stream_t *stream){    size_t res;    unsigned long remain;    if (stream->file)	return fread(ptr, size, nmemb, stream->file);    if (rar_eof(stream))	return 0;    res = size * nmemb;    remain = stream->size - stream->pos;    if (res > remain)	res = remain / size * size;    memcpy(ptr, stream->data + stream->pos, res);    stream->pos += res;    res /= size;    return res;}#elsetypedef FILE rar_stream_t;#define rar_open	fopen#define rar_close	fclose#define rar_eof		feof#define rar_tell	ftell#define rar_seek	fseek#define rar_getc	getc#define rar_read	fread#endif/**********************************************************************/static ssize_tgetline(char **lineptr, size_t *n, rar_stream_t *stream){    size_t res = 0;    int c;    if (*lineptr == NULL) {	*lineptr = malloc(4096);	if (*lineptr)	    *n = 4096;    }    else if (*n == 0) {	char *tmp = realloc(*lineptr, 4096);	if (tmp) {	    *lineptr = tmp;	    *n = 4096;	}    }    if (*lineptr == NULL || *n == 0)	return -1;    for (c = rar_getc(stream); c != EOF; c = rar_getc(stream)) {	if (res + 1 >= *n) {	    char *tmp = realloc(*lineptr, *n * 2);	    if (tmp == NULL)		return -1;	    *lineptr = tmp;	    *n *= 2;	}	(*lineptr)[res++] = c;	if (c == '\n') {	    (*lineptr)[res] = 0;	    return res;	}    }    if (res == 0)	return -1;    (*lineptr)[res] = 0;    return res;}/********************************************************************** * MPEG parsing **********************************************************************/typedef struct {    rar_stream_t *stream;    unsigned int pts;    int aid;    unsigned char *packet;    unsigned int packet_reserve;    unsigned int packet_size;} mpeg_t;static mpeg_t *mpeg_open(const char *filename){    mpeg_t *res = malloc(sizeof(mpeg_t));    int err = res == NULL;    if (!err) {	res->pts = 0;	res->aid = -1;	res->packet = NULL;	res->packet_size = 0;	res->packet_reserve = 0;	res->stream = rar_open(filename, "rb");	err = res->stream == NULL;	if (err)	    perror("fopen Vobsub file failed");	if (err)	    free(res);    }    return err ? NULL : res;}static voidmpeg_free(mpeg_t *mpeg){    if (mpeg->packet)	free(mpeg->packet);    if (mpeg->stream)	rar_close(mpeg->stream);    free(mpeg);}static intmpeg_eof(mpeg_t *mpeg){    return rar_eof(mpeg->stream);}static off_tmpeg_tell(mpeg_t *mpeg){    return rar_tell(mpeg->stream);}static intmpeg_run(mpeg_t *mpeg){    unsigned int len, idx, version;    int c;    /* Goto start of a packet, it starts with 0x000001?? */    const unsigned char wanted[] = { 0, 0, 1 };    unsigned char buf[5];    mpeg->aid = -1;    mpeg->packet_size = 0;    if (rar_read(buf, 4, 1, mpeg->stream) != 1)	return -1;    while (memcmp(buf, wanted, sizeof(wanted)) != 0) {	c = rar_getc(mpeg->stream);	if (c < 0)	    return -1;	memmove(buf, buf + 1, 3);	buf[3] = c;    }    switch (buf[3]) {    case 0xb9:			/* System End Code */	break;    case 0xba:			/* Packet start code */	c = rar_getc(mpeg->stream);	if (c < 0)	    return -1;	if ((c & 0xc0) == 0x40)	    version = 4;	else if ((c & 0xf0) == 0x20)	    version = 2;	else {	    mp_msg(MSGT_VOBSUB,MSGL_ERR, "VobSub: Unsupported MPEG version: 0x%02x\n", c);	    return -1;	}	if (version == 4) {	    if (rar_seek(mpeg->stream, 9, SEEK_CUR))		return -1;	}	else if (version == 2) {	    if (rar_seek(mpeg->stream, 7, SEEK_CUR))		return -1;	}	else	    abort();	break;    case 0xbd:			/* packet */	if (rar_read(buf, 2, 1, mpeg->stream) != 1)	    return -1;	len = buf[0] << 8 | buf[1];	idx = mpeg_tell(mpeg);	c = rar_getc(mpeg->stream);	if (c < 0)	    return -1;	if ((c & 0xC0) == 0x40) { /* skip STD scale & size */	    if (rar_getc(mpeg->stream) < 0)		return -1;	    c = rar_getc(mpeg->stream);	    if (c < 0)		return -1;	}	if ((c & 0xf0) == 0x20) { /* System-1 stream timestamp */	    /* Do we need this? */	    abort();	}	else if ((c & 0xf0) == 0x30) {	    /* Do we need this? */	    abort();	}	else if ((c & 0xc0) == 0x80) { /* System-2 (.VOB) stream */	    unsigned int pts_flags, hdrlen, dataidx;	    c = rar_getc(mpeg->stream);	    if (c < 0)		return -1;	    pts_flags = c;	    c = rar_getc(mpeg->stream);	    if (c < 0)		return -1;	    hdrlen = c;	    dataidx = mpeg_tell(mpeg) + hdrlen;	    if (dataidx > idx + len) {		mp_msg(MSGT_VOBSUB,MSGL_ERR, "Invalid header length: %d (total length: %d, idx: %d, dataidx: %d)\n",			hdrlen, len, idx, dataidx);		return -1;	    }	    if ((pts_flags & 0xc0) == 0x80) {		if (rar_read(buf, 5, 1, mpeg->stream) != 1)		    return -1;		if (!(((buf[0] & 0xf0) == 0x20) && (buf[0] & 1) && (buf[2] & 1) &&  (buf[4] & 1))) {		    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;		}		else		    mpeg->pts = ((buf[0] & 0x0e) << 29 | buf[1] << 22 | (buf[2] & 0xfe) << 14			| buf[3] << 7 | (buf[4] >> 1));	    }	    else /* if ((pts_flags & 0xc0) == 0xc0) */ {		/* what's this? */		/* abort(); */	    }	    rar_seek(mpeg->stream, dataidx, SEEK_SET);	    mpeg->aid = rar_getc(mpeg->stream);	    if (mpeg->aid < 0) {		mp_msg(MSGT_VOBSUB,MSGL_ERR, "Bogus aid %d\n", mpeg->aid);		return -1;	    }	    mpeg->packet_size = len - ((unsigned int) mpeg_tell(mpeg) - idx);	    if (mpeg->packet_reserve < mpeg->packet_size) {		if (mpeg->packet)		    free(mpeg->packet);		mpeg->packet = malloc(mpeg->packet_size);		if (mpeg->packet)		    mpeg->packet_reserve = mpeg->packet_size;	    }	    if (mpeg->packet == NULL) {		mp_msg(MSGT_VOBSUB,MSGL_FATAL,"malloc failure");		mpeg->packet_reserve = 0;		mpeg->packet_size = 0;		return -1;	    }	    if (rar_read(mpeg->packet, mpeg->packet_size, 1, mpeg->stream) != 1) {		mp_msg(MSGT_VOBSUB,MSGL_ERR,"fread failure");		mpeg->packet_size = 0;		return -1;	    }	    idx = len;	}	break;    case 0xbe:			/* Padding */	if (rar_read(buf, 2, 1, mpeg->stream) != 1)	    return -1;	len = buf[0] << 8 | buf[1];	if (len > 0 && rar_seek(mpeg->stream, len, SEEK_CUR))	    return -1;	break;    default:	if (0xc0 <= buf[3] && buf[3] < 0xf0) {	    /* MPEG audio or video */	    if (rar_read(buf, 2, 1, mpeg->stream) != 1)		return -1;	    len = buf[0] << 8 | buf[1];	    if (len > 0 && rar_seek(mpeg->stream, len, SEEK_CUR))		return -1;			}	else {	    mp_msg(MSGT_VOBSUB,MSGL_ERR,"unknown header 0x%02X%02X%02X%02X\n",		    buf[0], buf[1], buf[2], buf[3]);	    return -1;	}    }    return 0;}/********************************************************************** * Packet queue **********************************************************************/typedef struct {    unsigned int pts100;    off_t filepos;    unsigned int size;    unsigned char *data;} packet_t;typedef struct {    char *id;    packet_t *packets;    unsigned int packets_reserve;    unsigned int packets_size;    unsigned int current_index;} packet_queue_t;static voidpacket_construct(packet_t *pkt){    pkt->pts100 = 0;    pkt->filepos = 0;    pkt->size = 0;    pkt->data = NULL;}static voidpacket_destroy(packet_t *pkt){

⌨️ 快捷键说明

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