summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2010-03-10 02:36:35 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2010-03-10 02:36:35 +0200
commit4857965118bd0b272093f901167df35e22384c94 (patch)
treeca7217580f8d8b634ec35b0d853ffc88ecf3cbfb /stream
parentbc1d0ca37d9bdfd69a945043650e0246ffeb5f94 (diff)
parentbe23797ee7428e177b3476effb29beee4bfa7510 (diff)
downloadmpv-4857965118bd0b272093f901167df35e22384c94.tar.bz2
mpv-4857965118bd0b272093f901167df35e22384c94.tar.xz
Merge svn changes up to r30815
Diffstat (limited to 'stream')
-rw-r--r--stream/stream.c106
-rw-r--r--stream/stream.h2
-rw-r--r--stream/stream_cue.c211
3 files changed, 217 insertions, 102 deletions
diff --git a/stream/stream.c b/stream/stream.c
index 0b0cddc6f9..93eccdd659 100644
--- a/stream/stream.c
+++ b/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);
diff --git a/stream/stream.h b/stream/stream.h
index 3690dc46aa..7d6619f75b 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -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;
diff --git a/stream/stream_cue.c b/stream/stream_cue.c
index ee890894fc..a29783e4d5 100644
--- a/stream/stream_cue.c
+++ b/stream/stream_cue.c
@@ -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 * sector;
+}
- return VCD_SECTOR_DATA * cue_get_msf();
+static int seek(stream_t *s,off_t newpos) {
+ s->pos=newpos;
+ cue_set_msf(s->pos/VCD_SECTOR_DATA);
+ return 1;
}
-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 cue_vcd_seek_to_track (stream_t *stream, int track){
+ int pos;
+ if (cue_read_toc_entry (track))
+ return -1;
- return VCD_SECTOR_DATA * cue_get_msf();
+ 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);