mirror of https://github.com/mpv-player/mpv
Merge svn changes up to r30815
This commit is contained in:
commit
4857965118
|
@ -36,6 +36,7 @@ MPlayer (1.0)
|
|||
* support for displaying subs in the terminal (FIXME)
|
||||
* support for subtitles with audio-only files
|
||||
* support for right-to-left languages with embedded subtitles
|
||||
* support for UTF-16 encoded external subtitles
|
||||
* support for 8 channel audio
|
||||
* sync dvd:// and dvdnav:// features
|
||||
* support for MPEG-4 ASP in VDPAU video output (non B-frame only)
|
||||
|
|
106
stream/stream.c
106
stream/stream.c
|
@ -41,6 +41,7 @@
|
|||
#include "network.h"
|
||||
#include "stream.h"
|
||||
#include "libmpdemux/demuxer.h"
|
||||
#include "ffmpeg_files/intreadwrite.h"
|
||||
|
||||
#include "m_option.h"
|
||||
#include "m_struct.h"
|
||||
|
@ -493,9 +494,103 @@ int stream_check_interrupt(int time) {
|
|||
return stream_check_interrupt_cb(stream_check_interrupt_ctx, time);
|
||||
}
|
||||
|
||||
unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max) {
|
||||
/**
|
||||
* Helper function to read 16 bits little-endian and advance pointer
|
||||
*/
|
||||
static uint16_t get_le16_inc(const uint8_t **buf)
|
||||
{
|
||||
uint16_t v = AV_RL16(*buf);
|
||||
*buf += 2;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to read 16 bits big-endian and advance pointer
|
||||
*/
|
||||
static uint16_t get_be16_inc(const uint8_t **buf)
|
||||
{
|
||||
uint16_t v = AV_RB16(*buf);
|
||||
*buf += 2;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a newline character in buffer
|
||||
* \param buf buffer to search
|
||||
* \param len amount of bytes to search in buffer, may not overread
|
||||
* \param utf16 chose between UTF-8/ASCII/other and LE and BE UTF-16
|
||||
* 0 = UTF-8/ASCII/other, 1 = UTF-16-LE, 2 = UTF-16-BE
|
||||
*/
|
||||
static const uint8_t *find_newline(const uint8_t *buf, int len, int utf16)
|
||||
{
|
||||
uint32_t c;
|
||||
const uint8_t *end = buf + len;
|
||||
switch (utf16) {
|
||||
case 0:
|
||||
return (uint8_t *)memchr(buf, '\n', len);
|
||||
case 1:
|
||||
while (buf < end - 1) {
|
||||
GET_UTF16(c, buf < end - 1 ? get_le16_inc(&buf) : 0, return NULL;)
|
||||
if (buf <= end && c == '\n')
|
||||
return buf - 1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
while (buf < end - 1) {
|
||||
GET_UTF16(c, buf < end - 1 ? get_be16_inc(&buf) : 0, return NULL;)
|
||||
if (buf <= end && c == '\n')
|
||||
return buf - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a number of bytes, converting to UTF-8 if input is UTF-16
|
||||
* \param dst buffer to copy to
|
||||
* \param dstsize size of dst buffer
|
||||
* \param src buffer to copy from
|
||||
* \param len amount of bytes to copy from src
|
||||
* \param utf16 chose between UTF-8/ASCII/other and LE and BE UTF-16
|
||||
* 0 = UTF-8/ASCII/other, 1 = UTF-16-LE, 2 = UTF-16-BE
|
||||
*/
|
||||
static int copy_characters(uint8_t *dst, int dstsize,
|
||||
const uint8_t *src, int *len, int utf16)
|
||||
{
|
||||
uint32_t c;
|
||||
uint8_t *dst_end = dst + dstsize;
|
||||
const uint8_t *end = src + *len;
|
||||
switch (utf16) {
|
||||
case 0:
|
||||
if (*len > dstsize)
|
||||
*len = dstsize;
|
||||
memcpy(dst, src, *len);
|
||||
return *len;
|
||||
case 1:
|
||||
while (src < end - 1 && dst_end - dst > 8) {
|
||||
uint8_t tmp;
|
||||
GET_UTF16(c, src < end - 1 ? get_le16_inc(&src) : 0, ;)
|
||||
PUT_UTF8(c, tmp, *dst++ = tmp;)
|
||||
}
|
||||
*len -= end - src;
|
||||
return dstsize - (dst_end - dst);
|
||||
case 2:
|
||||
while (src < end - 1 && dst_end - dst > 8) {
|
||||
uint8_t tmp;
|
||||
GET_UTF16(c, src < end - 1 ? get_be16_inc(&src) : 0, ;)
|
||||
PUT_UTF8(c, tmp, *dst++ = tmp;)
|
||||
}
|
||||
*len -= end - src;
|
||||
return dstsize - (dst_end - dst);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max, int utf16) {
|
||||
int len;
|
||||
unsigned char* end,*ptr = mem;
|
||||
const unsigned char *end;
|
||||
unsigned char *ptr = mem;
|
||||
if (max < 1) return NULL;
|
||||
max--; // reserve one for 0-termination
|
||||
do {
|
||||
|
@ -504,13 +599,14 @@ unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max) {
|
|||
if(len <= 0 &&
|
||||
(!cache_stream_fill_buffer(s) ||
|
||||
(len = s->buf_len-s->buf_pos) <= 0)) break;
|
||||
end = (unsigned char*) memchr((void*)(s->buffer+s->buf_pos),'\n',len);
|
||||
end = find_newline(s->buffer+s->buf_pos, len, utf16);
|
||||
if(end) len = end - (s->buffer+s->buf_pos) + 1;
|
||||
if(len > 0 && max > 0) {
|
||||
int l = len > max ? max : len;
|
||||
memcpy(ptr,s->buffer+s->buf_pos,l);
|
||||
int l = copy_characters(ptr, max, s->buffer+s->buf_pos, &len, utf16);
|
||||
max -= l;
|
||||
ptr += l;
|
||||
if (!len)
|
||||
break;
|
||||
}
|
||||
s->buf_pos += len;
|
||||
} while(!end);
|
||||
|
|
|
@ -269,7 +269,7 @@ inline static int stream_read(stream_t *s,char* mem,int total){
|
|||
return total;
|
||||
}
|
||||
|
||||
unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max);
|
||||
unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max, int utf16);
|
||||
|
||||
inline static int stream_eof(stream_t *s){
|
||||
return s->eof;
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "m_struct.h"
|
||||
#include "libavutil/avstring.h"
|
||||
|
||||
#define byte unsigned char
|
||||
#define SIZERAW 2352
|
||||
#define SIZEISO_MODE1 2048
|
||||
#define SIZEISO_MODE2_RAW 2352
|
||||
|
@ -72,11 +71,6 @@ static const struct m_struct_st stream_opts = {
|
|||
stream_opts_fields
|
||||
};
|
||||
|
||||
static FILE* fd_cue;
|
||||
static int fd_bin = 0;
|
||||
|
||||
static char bin_filename[256];
|
||||
|
||||
static char cue_filename[256];
|
||||
static char bincue_path[256];
|
||||
|
||||
|
@ -122,7 +116,7 @@ static int digits2int(char s[2], int errval) {
|
|||
}
|
||||
|
||||
/* presumes Line is preloaded with the "current" line of the file */
|
||||
static int cue_getTrackinfo(char *Line, tTrack *track)
|
||||
static int cue_getTrackinfo(FILE *fd_cue, char *Line, tTrack *track)
|
||||
{
|
||||
int already_set = 0;
|
||||
|
||||
|
@ -178,9 +172,12 @@ static int cue_getTrackinfo(char *Line, tTrack *track)
|
|||
* sure the sizes are in sync.
|
||||
*/
|
||||
static int cue_find_bin (char *firstline) {
|
||||
const char *cur_name;
|
||||
int i,j;
|
||||
char bin_filename[256];
|
||||
char s[256];
|
||||
char t[256];
|
||||
int fd_bin;
|
||||
|
||||
/* get the filename out of that */
|
||||
/* 12345 6 */
|
||||
|
@ -213,71 +210,62 @@ static int cue_find_bin (char *firstline) {
|
|||
|
||||
}
|
||||
|
||||
/* now try to open that file, without path */
|
||||
fd_bin = open (bin_filename, O_RDONLY);
|
||||
if (fd_bin == -1)
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_STATUS, "[bincue] bin filename tested: %s\n",
|
||||
bin_filename);
|
||||
|
||||
/* now try to find it with the path of the cue file */
|
||||
snprintf(s,sizeof( s ),"%s/%s",bincue_path,bin_filename);
|
||||
fd_bin = open (s, O_RDONLY);
|
||||
if (fd_bin == -1)
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_STATUS,
|
||||
"[bincue] bin filename tested: %s\n", s);
|
||||
fd_bin = -1;
|
||||
for (i = 0; fd_bin == -1 && i < 6; i++) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
/* now try to open that file, without path */
|
||||
cur_name = bin_filename;
|
||||
break;
|
||||
case 1:
|
||||
/* now try to find it with the path of the cue file */
|
||||
snprintf(s,sizeof( s ),"%s/%s",bincue_path,bin_filename);
|
||||
cur_name = s;
|
||||
break;
|
||||
case 2:
|
||||
/* now I would say the whole filename is shit, build our own */
|
||||
strncpy(s, cue_filename, strlen(cue_filename) - 3 );
|
||||
s[strlen(cue_filename) - 3] = '\0';
|
||||
strcat(s, "bin");
|
||||
fd_bin = open (s, O_RDONLY);
|
||||
if (fd_bin == -1)
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_STATUS,
|
||||
"[bincue] bin filename tested: %s\n", s);
|
||||
|
||||
/* ok try it with path */
|
||||
snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
|
||||
fd_bin = open (t, O_RDONLY);
|
||||
if (fd_bin == -1)
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_STATUS,
|
||||
"[bincue] bin filename tested: %s\n",t);
|
||||
/* now I would say the whole filename is shit, build our own */
|
||||
strncpy(s, cue_filename, strlen(cue_filename) - 3 );
|
||||
s[strlen(cue_filename) - 3] = '\0';
|
||||
strcat(s, "img");
|
||||
fd_bin = open (s, O_RDONLY);
|
||||
if (fd_bin == -1)
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_STATUS,
|
||||
"[bincue] bin filename tested: %s\n", s);
|
||||
/* ok try it with path */
|
||||
snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
|
||||
fd_bin = open (t, O_RDONLY);
|
||||
if (fd_bin == -1)
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_STATUS,
|
||||
"[bincue] bin filename tested: %s\n", s);
|
||||
|
||||
/* I'll give up */
|
||||
mp_tmsg(MSGT_OPEN,MSGL_ERR,
|
||||
"[bincue] Couldn't find the bin file - giving up.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else strcpy(bin_filename, t);
|
||||
|
||||
} else strcpy(bin_filename, s);
|
||||
|
||||
} else strcpy(bin_filename, s);
|
||||
cur_name = s;
|
||||
break;
|
||||
case 3:
|
||||
/* ok try it with path */
|
||||
snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
|
||||
fd_bin = open (t, O_RDONLY);
|
||||
cur_name = t;
|
||||
break;
|
||||
case 4:
|
||||
/* now I would say the whole filename is shit, build our own */
|
||||
strncpy(s, cue_filename, strlen(cue_filename) - 3 );
|
||||
s[strlen(cue_filename) - 3] = '\0';
|
||||
strcat(s, "img");
|
||||
cur_name = s;
|
||||
break;
|
||||
case 5:
|
||||
/* ok try it with path */
|
||||
snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
|
||||
cur_name = t;
|
||||
break;
|
||||
}
|
||||
fd_bin = open(cur_name, O_RDONLY);
|
||||
if (fd_bin == -1) {
|
||||
mp_tmsg(MSGT_OPEN,MSGL_STATUS, "[bincue] bin filename tested: %s\n",
|
||||
cur_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (fd_bin == -1)
|
||||
{
|
||||
/* I'll give up */
|
||||
mp_tmsg(MSGT_OPEN,MSGL_ERR,
|
||||
"[bincue] Couldn't find the bin file - giving up.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mp_tmsg(MSGT_OPEN,MSGL_INFO,
|
||||
"[bincue] Using bin file %s.\n", bin_filename);
|
||||
return 0;
|
||||
"[bincue] Using bin file %s.\n", cur_name);
|
||||
return fd_bin;
|
||||
}
|
||||
|
||||
static inline int cue_msf_2_sector(int minute, int second, int frame) {
|
||||
|
@ -324,12 +312,12 @@ static int cue_read_cue (char *in_cue_filename)
|
|||
unsigned int sect;
|
||||
char *s,*t;
|
||||
int i;
|
||||
int fd_bin;
|
||||
FILE *fd_cue;
|
||||
|
||||
/* we have no tracks at the beginning */
|
||||
nTracks = 0;
|
||||
|
||||
fd_bin = 0;
|
||||
|
||||
/* split the filename into a path and filename part */
|
||||
s = strdup(in_cue_filename);
|
||||
t = strrchr(s, '/');
|
||||
|
@ -344,6 +332,8 @@ static int cue_read_cue (char *in_cue_filename)
|
|||
|
||||
av_strlcpy(bincue_path,t,sizeof( bincue_path ));
|
||||
mp_msg(MSGT_OPEN,MSGL_V,"dirname: %s, cuepath: %s\n", t, bincue_path);
|
||||
free(s);
|
||||
s = t = NULL;
|
||||
|
||||
/* no path at all? */
|
||||
if (strcmp(bincue_path, ".") == 0) {
|
||||
|
@ -368,7 +358,7 @@ static int cue_read_cue (char *in_cue_filename)
|
|||
/* read the first line and hand it to find_bin, which will
|
||||
test more than one possible name of the file */
|
||||
|
||||
if(! fgets( sLine, 256, fd_cue ) )
|
||||
if(! fgets( sLine, sizeof(sLine), fd_cue ) )
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_ERR,
|
||||
"[bincue] Error reading from %s\n", in_cue_filename);
|
||||
|
@ -376,7 +366,8 @@ static int cue_read_cue (char *in_cue_filename)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (cue_find_bin(sLine)) {
|
||||
fd_bin = cue_find_bin(sLine);
|
||||
if (fd_bin == -1) {
|
||||
fclose (fd_cue);
|
||||
return -1;
|
||||
}
|
||||
|
@ -384,7 +375,7 @@ static int cue_read_cue (char *in_cue_filename)
|
|||
|
||||
/* now build the track list */
|
||||
/* red the next line and call our track finder */
|
||||
if(! fgets( sLine, 256, fd_cue ) )
|
||||
if(! fgets( sLine, sizeof(sLine), fd_cue ) )
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_ERR,
|
||||
"[bincue] Error reading from %s\n", in_cue_filename);
|
||||
|
@ -394,7 +385,7 @@ static int cue_read_cue (char *in_cue_filename)
|
|||
|
||||
while(!feof(fd_cue))
|
||||
{
|
||||
if (cue_getTrackinfo(sLine, &tracks[nTracks++]) != 0)
|
||||
if (cue_getTrackinfo(fd_cue, sLine, &tracks[nTracks++]) != 0)
|
||||
{
|
||||
mp_tmsg(MSGT_OPEN,MSGL_ERR,
|
||||
"[bincue] Error reading from %s\n", in_cue_filename);
|
||||
|
@ -449,15 +440,14 @@ static int cue_read_cue (char *in_cue_filename)
|
|||
|
||||
|
||||
|
||||
static int cue_read_toc_entry(void) {
|
||||
|
||||
int track = cue_current_pos.track - 1;
|
||||
|
||||
static int cue_read_toc_entry(int track) {
|
||||
/* check if its a valid track, if not return -1 */
|
||||
if (track >= nTracks)
|
||||
if (track <= 0 || track > nTracks)
|
||||
return -1;
|
||||
|
||||
|
||||
cue_current_pos.track = track;
|
||||
track--;
|
||||
switch (tracks[track].mode)
|
||||
{
|
||||
case AUDIO:
|
||||
|
@ -479,21 +469,29 @@ static int cue_read_toc_entry(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cue_vcd_seek_to_track (int track){
|
||||
cue_current_pos.track = track;
|
||||
static int cue_vcd_get_track_end (int track){
|
||||
int sector = cue_msf_2_sector(tracks[track].minute, tracks[track].second,
|
||||
tracks[track].frame);
|
||||
|
||||
if (cue_read_toc_entry ())
|
||||
return -1;
|
||||
|
||||
return VCD_SECTOR_DATA * cue_get_msf();
|
||||
return VCD_SECTOR_DATA * sector;
|
||||
}
|
||||
|
||||
static int cue_vcd_get_track_end (int track){
|
||||
cue_current_pos.frame = tracks[track].frame;
|
||||
cue_current_pos.second = tracks[track].second;
|
||||
cue_current_pos.minute = tracks[track].minute;
|
||||
static int seek(stream_t *s,off_t newpos) {
|
||||
s->pos=newpos;
|
||||
cue_set_msf(s->pos/VCD_SECTOR_DATA);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return VCD_SECTOR_DATA * cue_get_msf();
|
||||
static int cue_vcd_seek_to_track (stream_t *stream, int track){
|
||||
int pos;
|
||||
if (cue_read_toc_entry (track))
|
||||
return -1;
|
||||
|
||||
pos = VCD_SECTOR_DATA * cue_get_msf();
|
||||
stream->start_pos = pos;
|
||||
stream->end_pos = cue_vcd_get_track_end(track);
|
||||
seek(stream, pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void cue_vcd_read_toc(void){
|
||||
|
@ -513,6 +511,7 @@ static void cue_vcd_read_toc(void){
|
|||
|
||||
static int cue_vcd_read(stream_t *stream, char *mem, int size) {
|
||||
unsigned long position;
|
||||
int fd_bin = stream->fd;
|
||||
int track = cue_current_pos.track - 1;
|
||||
|
||||
position = tracks[track].start_offset +
|
||||
|
@ -549,16 +548,35 @@ static int cue_vcd_read(stream_t *stream, char *mem, int size) {
|
|||
return VCD_SECTOR_DATA;
|
||||
}
|
||||
|
||||
static int seek(stream_t *s,off_t newpos) {
|
||||
s->pos=newpos;
|
||||
cue_set_msf(s->pos/VCD_SECTOR_DATA);
|
||||
return 1;
|
||||
static int control(stream_t *stream, int cmd, void *arg) {
|
||||
switch(cmd) {
|
||||
case STREAM_CTRL_GET_NUM_CHAPTERS:
|
||||
{
|
||||
*(unsigned int *)arg = nTracks;
|
||||
return STREAM_OK;
|
||||
}
|
||||
case STREAM_CTRL_SEEK_TO_CHAPTER:
|
||||
{
|
||||
int r;
|
||||
unsigned int track = *(unsigned int *)arg + 1;
|
||||
r = cue_vcd_seek_to_track(stream, track);
|
||||
if (r >= 0) {
|
||||
return STREAM_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STREAM_CTRL_GET_CURRENT_CHAPTER:
|
||||
{
|
||||
*(unsigned int *)arg = cue_current_pos.track - 1;
|
||||
return STREAM_OK;
|
||||
}
|
||||
}
|
||||
return STREAM_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
|
||||
struct stream_priv_s* p = (struct stream_priv_s*)opts;
|
||||
int ret,ret2,f,track = 0;
|
||||
int ret,f,track = 0;
|
||||
char *filename = NULL, *colon = NULL;
|
||||
|
||||
if(mode != STREAM_READ || !p->filename) {
|
||||
|
@ -585,23 +603,24 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
|
|||
return STREAM_UNSUPPORTED;
|
||||
}
|
||||
cue_vcd_read_toc();
|
||||
ret2=cue_vcd_get_track_end(track);
|
||||
ret=cue_vcd_seek_to_track(track);
|
||||
ret=cue_vcd_seek_to_track(stream, track);
|
||||
if(ret<0){
|
||||
mp_msg(MSGT_OPEN, MSGL_ERR, "%s (seek)\n",
|
||||
mp_gtext("Error selecting VCD track."));
|
||||
return STREAM_UNSUPPORTED;
|
||||
}
|
||||
mp_tmsg(MSGT_OPEN,MSGL_INFO,"CUE stream_open, filename=%s, track=%d, available tracks: %d -> %d\n", filename, track, ret, ret2);
|
||||
mp_tmsg(MSGT_OPEN, MSGL_INFO,
|
||||
"CUE stream_open, filename=%s, track=%d, "
|
||||
"available tracks: %d -> %d\n",
|
||||
filename, track, ret, (int)stream->end_pos);
|
||||
|
||||
stream->fd = f;
|
||||
stream->type = STREAMTYPE_VCDBINCUE;
|
||||
stream->sector_size = VCD_SECTOR_DATA;
|
||||
stream->flags = STREAM_READ | MP_STREAM_SEEK_FW;
|
||||
stream->start_pos = ret;
|
||||
stream->end_pos = ret2;
|
||||
stream->fill_buffer = cue_vcd_read;
|
||||
stream->seek = seek;
|
||||
stream->control = control;
|
||||
|
||||
free(filename);
|
||||
m_struct_free(&stream_opts,opts);
|
||||
|
|
95
subreader.c
95
subreader.c
|
@ -111,7 +111,7 @@ static char *stristr(const char *haystack, const char *needle) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_sami(stream_t* st, subtitle *current) {
|
||||
static subtitle *sub_read_line_sami(stream_t* st, subtitle *current, int utf16) {
|
||||
static char line[LINE_LEN+1];
|
||||
static char *s = NULL, *slacktime_s;
|
||||
char text[LINE_LEN+1], *p=NULL, *q;
|
||||
|
@ -123,7 +123,7 @@ static subtitle *sub_read_line_sami(stream_t* st, subtitle *current) {
|
|||
|
||||
/* read the first line */
|
||||
if (!s)
|
||||
if (!(s = stream_read_line(st, line, LINE_LEN))) return 0;
|
||||
if (!(s = stream_read_line(st, line, LINE_LEN, utf16))) return 0;
|
||||
|
||||
do {
|
||||
switch (state) {
|
||||
|
@ -230,7 +230,7 @@ static subtitle *sub_read_line_sami(stream_t* st, subtitle *current) {
|
|||
}
|
||||
|
||||
/* read next line */
|
||||
if (state != 99 && !(s = stream_read_line (st, line, LINE_LEN))) {
|
||||
if (state != 99 && !(s = stream_read_line (st, line, LINE_LEN, utf16))) {
|
||||
if (current->start > 0) {
|
||||
break; // if it is the last subtitle
|
||||
} else {
|
||||
|
@ -274,14 +274,14 @@ static char *sub_readtext(char *source, char **dest) {
|
|||
else return NULL; // last text field
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
char line2[LINE_LEN+1];
|
||||
char *p, *next;
|
||||
int i;
|
||||
|
||||
do {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
} while ((sscanf (line,
|
||||
"{%ld}{}%[^\r\n]",
|
||||
&(current->start), line2) < 2) &&
|
||||
|
@ -302,14 +302,14 @@ static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
char line2[LINE_LEN+1];
|
||||
char *p, *next;
|
||||
int i;
|
||||
|
||||
do {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
} while ((sscanf (line,
|
||||
"[%ld][%ld]%[^\r\n]",
|
||||
&(current->start), &(current->end), line2) < 3));
|
||||
|
@ -328,19 +328,19 @@ static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current) {
|
||||
static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
int a1,a2,a3,a4,b1,b2,b3,b4;
|
||||
char *p=NULL, *q=NULL;
|
||||
int len;
|
||||
|
||||
while (1) {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) continue;
|
||||
current->start = a1*360000+a2*6000+a3*100+a4;
|
||||
current->end = b1*360000+b2*6000+b3*100+b4;
|
||||
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
|
||||
p=q=line;
|
||||
for (current->lines=1; current->lines < SUB_MAX_TEXT; current->lines++) {
|
||||
|
@ -358,21 +358,21 @@ static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
int a1,a2,a3,a4,b1,b2,b3,b4;
|
||||
char *p=NULL;
|
||||
int i,len;
|
||||
|
||||
while (!current->text[0]) {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
if ((len=sscanf (line, "%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d",&a1,&a2,&a3,(char *)&i,&a4,&b1,&b2,&b3,(char *)&i,&b4)) < 10)
|
||||
continue;
|
||||
current->start = a1*360000+a2*6000+a3*100+a4/10;
|
||||
current->end = b1*360000+b2*6000+b3*100+b4/10;
|
||||
for (i=0; i<SUB_MAX_TEXT;) {
|
||||
int blank = 1;
|
||||
if (!stream_read_line (st, line, LINE_LEN)) break;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) break;
|
||||
len=0;
|
||||
for (p=line; *p!='\n' && *p!='\r' && *p; p++,len++)
|
||||
if (*p != ' ' && *p != '\t')
|
||||
|
@ -410,21 +410,21 @@ static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
int a1,a2,a3,a4;
|
||||
char *p=NULL;
|
||||
int i,len;
|
||||
|
||||
while (!current->text[0]) {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
if (line[0]!='{')
|
||||
continue;
|
||||
if ((len=sscanf (line, "{T %d:%d:%d:%d",&a1,&a2,&a3,&a4)) < 4)
|
||||
continue;
|
||||
current->start = a1*360000+a2*6000+a3*100+a4/10;
|
||||
for (i=0; i<SUB_MAX_TEXT;) {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) break;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) break;
|
||||
if (line[0]=='}') break;
|
||||
len=0;
|
||||
for (p=line; *p!='\n' && *p!='\r' && *p; ++p,++len);
|
||||
|
@ -443,14 +443,14 @@ static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current) {
|
|||
}
|
||||
|
||||
|
||||
static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
int a1,a2,a3;
|
||||
char *p=NULL, *next,separator;
|
||||
int i,len,plen;
|
||||
|
||||
while (!current->text[0]) {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
if ((len=sscanf (line, "%d:%d:%d%c%n",&a1,&a2,&a3,&separator,&plen)) < 4)
|
||||
continue;
|
||||
|
||||
|
@ -489,7 +489,7 @@ static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_rt(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_rt(stream_t *st,subtitle *current, int utf16) {
|
||||
//TODO: This format uses quite rich (sub/super)set of xhtml
|
||||
// I couldn't check it since DTD is not included.
|
||||
// WARNING: full XML parses can be required for proper parsing
|
||||
|
@ -499,7 +499,7 @@ static subtitle *sub_read_line_rt(stream_t *st,subtitle *current) {
|
|||
int i,len,plen;
|
||||
|
||||
while (!current->text[0]) {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
//TODO: it seems that format of time is not easily determined, it may be 1:12, 1:12.0 or 0:1:12.0
|
||||
//to describe the same moment in time. Maybe there are even more formats in use.
|
||||
//if ((len=sscanf (line, "<Time Begin=\"%d:%d:%d.%d\" End=\"%d:%d:%d.%d\"",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8)
|
||||
|
@ -539,7 +539,7 @@ static subtitle *sub_read_line_rt(stream_t *st,subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current, int utf16) {
|
||||
/*
|
||||
* Sub Station Alpha v4 (and v2?) scripts have 9 commas before subtitle
|
||||
* other Sub Station Alpha scripts have only 8 commas before subtitle
|
||||
|
@ -563,7 +563,7 @@ static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current) {
|
|||
char *tmp;
|
||||
|
||||
do {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL;
|
||||
} while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d,"
|
||||
"%[^\n\r]", ¬hing,
|
||||
&hour1, &min1, &sec1, &hunsec1,
|
||||
|
@ -640,11 +640,11 @@ static void sub_pp_ssa(subtitle *sub) {
|
|||
*
|
||||
* by set, based on code by szabi (dunnowhat sub format ;-)
|
||||
*/
|
||||
static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
char text[LINE_LEN+1], *s, *d;
|
||||
|
||||
if (!stream_read_line (st, line, LINE_LEN))
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16))
|
||||
return NULL;
|
||||
/* skip spaces */
|
||||
for (s=line; *s && isspace(*s); s++);
|
||||
|
@ -678,7 +678,7 @@ static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current) {
|
||||
static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
float a,b;
|
||||
int num=0;
|
||||
|
@ -686,7 +686,7 @@ static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current) {
|
|||
|
||||
do
|
||||
{
|
||||
if (!stream_read_line(st, line, LINE_LEN)) return NULL;
|
||||
if (!stream_read_line(st, line, LINE_LEN, utf16)) return NULL;
|
||||
} while (sscanf (line, "%f %f", &a, &b) !=2);
|
||||
|
||||
mpsub_position += a*mpsub_multiplier;
|
||||
|
@ -695,7 +695,7 @@ static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current) {
|
|||
current->end=(int) mpsub_position;
|
||||
|
||||
while (num < SUB_MAX_TEXT) {
|
||||
if (!stream_read_line (st, line, LINE_LEN)) {
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16)) {
|
||||
if (num == 0) return NULL;
|
||||
else return current;
|
||||
}
|
||||
|
@ -723,14 +723,14 @@ static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current) {
|
|||
subtitle *previous_aqt_sub = NULL;
|
||||
#endif
|
||||
|
||||
static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
char *next;
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
// try to locate next subtitle
|
||||
if (!stream_read_line (st, line, LINE_LEN))
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16))
|
||||
return NULL;
|
||||
if (!(sscanf (line, "-->> %ld", &(current->start)) <1))
|
||||
break;
|
||||
|
@ -745,14 +745,14 @@ static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current) {
|
|||
previous_aqt_sub = current;
|
||||
#endif
|
||||
|
||||
if (!stream_read_line (st, line, LINE_LEN))
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16))
|
||||
return NULL;
|
||||
|
||||
sub_readtext((char *) &line,¤t->text[0]);
|
||||
current->lines = 1;
|
||||
current->end = current->start; // will be corrected by next subtitle
|
||||
|
||||
if (!stream_read_line (st, line, LINE_LEN))
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16))
|
||||
return current;
|
||||
|
||||
next = line,i=1;
|
||||
|
@ -780,7 +780,7 @@ static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current) {
|
|||
subtitle *previous_subrip09_sub = NULL;
|
||||
#endif
|
||||
|
||||
static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current) {
|
||||
static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
int a1,a2,a3;
|
||||
char * next=NULL;
|
||||
|
@ -788,7 +788,7 @@ static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current) {
|
|||
|
||||
while (1) {
|
||||
// try to locate next subtitle
|
||||
if (!stream_read_line (st, line, LINE_LEN))
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16))
|
||||
return NULL;
|
||||
if (!((len=sscanf (line, "[%d:%d:%d]",&a1,&a2,&a3)) < 3))
|
||||
break;
|
||||
|
@ -805,7 +805,7 @@ static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current) {
|
|||
previous_subrip09_sub = current;
|
||||
#endif
|
||||
|
||||
if (!stream_read_line (st, line, LINE_LEN))
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16))
|
||||
return NULL;
|
||||
|
||||
next = line,i=0;
|
||||
|
@ -832,7 +832,7 @@ static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current) {
|
|||
return current;
|
||||
}
|
||||
|
||||
static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current)
|
||||
static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current, int utf16)
|
||||
{
|
||||
char line1[LINE_LEN], line2[LINE_LEN], directive[LINE_LEN], *p, *q;
|
||||
unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0;
|
||||
|
@ -844,7 +844,7 @@ static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current)
|
|||
memset(line2, 0, LINE_LEN);
|
||||
memset(directive, 0, LINE_LEN);
|
||||
while (!current->text[0]) {
|
||||
if (!stream_read_line(st, line1, LINE_LEN)) {
|
||||
if (!stream_read_line(st, line1, LINE_LEN, utf16)) {
|
||||
return NULL;
|
||||
}
|
||||
if (sscanf
|
||||
|
@ -1002,7 +1002,7 @@ static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current)
|
|||
(*(p + 1) == '~') || (*(p + 1) == '{')) {
|
||||
++p;
|
||||
} else if (eol(*(p + 1))) {
|
||||
if (!stream_read_line(st, directive, LINE_LEN))
|
||||
if (!stream_read_line(st, directive, LINE_LEN, utf16))
|
||||
return NULL;
|
||||
trail_space(directive);
|
||||
av_strlcat(line2, directive, LINE_LEN);
|
||||
|
@ -1022,14 +1022,14 @@ static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current)
|
|||
return current;
|
||||
}
|
||||
|
||||
static int sub_autodetect (stream_t* st, int *uses_time) {
|
||||
static int sub_autodetect (stream_t* st, int *uses_time, int utf16) {
|
||||
char line[LINE_LEN+1];
|
||||
int i,j=0;
|
||||
char p;
|
||||
|
||||
while (j < 100) {
|
||||
j++;
|
||||
if (!stream_read_line (st, line, LINE_LEN))
|
||||
if (!stream_read_line (st, line, LINE_LEN, utf16))
|
||||
return SUB_INVALID;
|
||||
|
||||
if (sscanf (line, "{%d}{%d}", &i, &i)==2)
|
||||
|
@ -1283,7 +1283,7 @@ static void adjust_subs_time(subtitle* sub, float subtime, float fps, int block,
|
|||
}
|
||||
|
||||
struct subreader {
|
||||
subtitle * (*read)(stream_t *st,subtitle *dest);
|
||||
subtitle * (*read)(stream_t *st,subtitle *dest,int utf16);
|
||||
void (*post)(subtitle *dest);
|
||||
const char *name;
|
||||
};
|
||||
|
@ -1350,6 +1350,7 @@ const char* guess_cp(stream_t *st, const char *preferred_language, const char *f
|
|||
#endif
|
||||
|
||||
sub_data* sub_read_file (char *filename, float fps) {
|
||||
int utf16;
|
||||
stream_t* fd;
|
||||
int n_max, n_first, i, j, sub_first, sub_orig;
|
||||
subtitle *first, *second, *sub, *return_sub, *alloced_sub = NULL;
|
||||
|
@ -1378,15 +1379,19 @@ sub_data* sub_read_file (char *filename, float fps) {
|
|||
i = 0;
|
||||
fd=open_stream (filename, NULL, &i); if (!fd) return NULL;
|
||||
|
||||
sub_format=sub_autodetect (fd, &uses_time);
|
||||
sub_format = SUB_INVALID;
|
||||
for (utf16 = 0; sub_format == SUB_INVALID && utf16 < 3; utf16++) {
|
||||
sub_format=sub_autodetect (fd, &uses_time, utf16);
|
||||
stream_reset(fd);
|
||||
stream_seek(fd,0);
|
||||
}
|
||||
utf16--;
|
||||
|
||||
mpsub_multiplier = (uses_time ? 100.0 : 1.0);
|
||||
if (sub_format==SUB_INVALID) {mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: Could not determine file format\n");return NULL;}
|
||||
srp=sr+sub_format;
|
||||
mp_msg(MSGT_SUBREADER, MSGL_V, "SUB: Detected subtitle file format: %s\n", srp->name);
|
||||
|
||||
stream_reset(fd);
|
||||
stream_seek(fd,0);
|
||||
|
||||
#ifdef CONFIG_ICONV
|
||||
sub_utf8_prev=sub_utf8;
|
||||
{
|
||||
|
@ -1430,7 +1435,7 @@ sub_data* sub_read_file (char *filename, float fps) {
|
|||
sub = &first[sub_num];
|
||||
#endif
|
||||
memset(sub, '\0', sizeof(subtitle));
|
||||
sub=srp->read(fd,sub);
|
||||
sub=srp->read(fd,sub,utf16);
|
||||
if(!sub) break; // EOF
|
||||
#ifdef CONFIG_ICONV
|
||||
if ((sub!=ERR) && sub_utf8 == 2) sub=subcp_recode(sub);
|
||||
|
|
Loading…
Reference in New Issue