summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
Diffstat (limited to 'stream')
-rw-r--r--stream/cache2.c20
-rw-r--r--stream/network.c7
-rw-r--r--stream/network.h2
-rw-r--r--stream/stream.c24
-rw-r--r--stream/stream_dvdnav.c7
-rw-r--r--stream/stream_ffmpeg.c1
-rw-r--r--stream/stream_file.c12
-rw-r--r--stream/stream_smb.c12
8 files changed, 76 insertions, 9 deletions
diff --git a/stream/cache2.c b/stream/cache2.c
index 9e4bea35b4..e930d72255 100644
--- a/stream/cache2.c
+++ b/stream/cache2.c
@@ -167,6 +167,7 @@ static int cache_fill(cache_vars_t *s)
int back,back2,newb,space,len,pos;
off_t read=s->read_filepos;
int read_chunk;
+ int wraparound_copy = 0;
if(read<s->min_filepos || read>s->max_filepos){
// seek...
@@ -208,8 +209,16 @@ static int cache_fill(cache_vars_t *s)
// printf("### read=0x%X back=%d newb=%d space=%d pos=%d\n",read,back,newb,space,pos);
- // reduce space if needed:
- if(space>s->buffer_size-pos) space=s->buffer_size-pos;
+ // try to avoid wrap-around. If not possible due to sector size
+ // do an extra copy.
+ if(space>s->buffer_size-pos) {
+ if (s->buffer_size-pos >= s->sector_size) {
+ space=s->buffer_size-pos;
+ } else {
+ space = s->sector_size;
+ wraparound_copy = 1;
+ }
+ }
// limit one-time block size
read_chunk = s->stream->read_chunk;
@@ -224,6 +233,13 @@ static int cache_fill(cache_vars_t *s)
s->min_filepos=read-back; // avoid seeking-back to temp area...
#endif
+ if (wraparound_copy) {
+ int to_copy;
+ len = stream_read_internal(s->stream, s->stream->buffer, space);
+ to_copy = FFMIN(len, s->buffer_size-pos);
+ memcpy(s->buffer + pos, s->stream->buffer, to_copy);
+ memcpy(s->buffer, s->stream->buffer + to_copy, len - to_copy);
+ } else
len = stream_read_internal(s->stream, &s->buffer[pos], space);
s->eof= !len;
diff --git a/stream/network.c b/stream/network.c
index c6776ac29a..b722023061 100644
--- a/stream/network.c
+++ b/stream/network.c
@@ -58,6 +58,7 @@ int network_bandwidth=0;
int network_cookies_enabled = 0;
char *network_useragent=NULL;
char *network_referrer=NULL;
+char **network_http_header_fields=NULL;
/* IPv6 options */
int network_ipv4_only_proxy = 0;
@@ -250,6 +251,12 @@ http_send_request( URL_t *url, off_t pos ) {
if (network_cookies_enabled) cookies_set( http_hdr, server_url->hostname, server_url->url );
+ if (network_http_header_fields) {
+ int i=0;
+ while (network_http_header_fields[i])
+ http_set_field(http_hdr, network_http_header_fields[i++]);
+ }
+
http_set_field( http_hdr, "Connection: close");
if (proxy)
http_add_basic_proxy_authentication(http_hdr, url->username, url->password);
diff --git a/stream/network.h b/stream/network.h
index 1c395acc49..33b668c516 100644
--- a/stream/network.h
+++ b/stream/network.h
@@ -61,6 +61,8 @@ typedef struct {
extern const mime_struct_t mime_type_table[];
+extern char **network_http_header_fields;
+
streaming_ctrl_t *streaming_ctrl_new(void);
int streaming_bufferize( streaming_ctrl_t *streaming_ctrl, char *buffer, int size);
diff --git a/stream/stream.c b/stream/stream.c
index 86dd61389e..9a3f25f8ab 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -28,6 +28,7 @@
#endif
#include <fcntl.h>
#include <strings.h>
+#include <assert.h>
#include "talloc.h"
@@ -279,6 +280,7 @@ void stream_capture_do(stream_t *s)
int stream_read_internal(stream_t *s, void *buf, int len)
{
+ int orig_len = len;
// we will retry even if we already reached EOF previously.
switch(s->type){
case STREAMTYPE_STREAM:
@@ -300,7 +302,26 @@ int stream_read_internal(stream_t *s, void *buf, int len)
default:
len= s->fill_buffer ? s->fill_buffer(s, buf, len) : 0;
}
- if(len<=0){ s->eof=1; return 0; }
+ if(len<=0){
+ // dvdnav has some horrible hacks to "suspend" reads,
+ // we need to skip this code or seeks will hang.
+ if (!s->eof && s->type != STREAMTYPE_DVDNAV) {
+ // just in case this is an error e.g. due to network
+ // timeout reset and retry
+ // Seeking is used as a hack to make network streams
+ // reopen the connection, ideally they would implement
+ // e.g. a STREAM_CTRL_RECONNECT to do this
+ off_t pos = s->pos;
+ s->eof=1;
+ stream_reset(s);
+ stream_seek_internal(s, pos);
+ // make sure EOF is set to ensure no endless loops
+ s->eof=1;
+ return stream_read_internal(s, buf, orig_len);
+ }
+ s->eof=1;
+ return 0;
+ }
// When reading succeeded we are obviously not at eof.
// This e.g. avoids issues with eof getting stuck when lavf seeks in MPEG-TS
s->eof=0;
@@ -328,6 +349,7 @@ int stream_write_buffer(stream_t *s, unsigned char *buf, int len) {
if(rd < 0)
return -1;
s->pos += rd;
+ assert(rd == len && "stream_write_buffer(): unexpected short write");
return rd;
}
diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c
index b1c51e68e9..d5b12dc9f6 100644
--- a/stream/stream_dvdnav.c
+++ b/stream/stream_dvdnav.c
@@ -134,7 +134,7 @@ static dvdnav_priv_t * new_dvdnav_stream(char * filename) {
mp_msg(MSGT_OPEN,MSGL_ERR,"stream_dvdnav, failed to set PGC positioning\n");
/* report the title?! */
if (dvdnav_get_title_string(priv->dvdnav,&title_str)==DVDNAV_STATUS_OK) {
- mp_msg(MSGT_IDENTIFY, MSGL_INFO,"Title: '%s'\n",title_str);
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_VOLUME_ID=%s\n", title_str);
}
//dvdnav_event_clear(priv);
@@ -509,7 +509,9 @@ static void identify_chapters(dvdnav_t *nav, uint32_t title)
if(parts) {
t = duration / 90;
mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_TITLE_%d_LENGTH=%d.%03d\n", title, t / 1000, t % 1000);
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_CHAPTERS=%d\n", title, n);
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "TITLE %u, CHAPTERS: ", title);
+
for(i=0; i<n; i++) {
t = parts[i] / 90000;
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "%02d:%02d:%02d,", t/3600, (t/60)%60, t%60);
@@ -524,7 +526,7 @@ static void identify(dvdnav_priv_t *priv, struct stream_priv_s *p)
uint32_t titles=0, i;
if(p->track <= 0) {
dvdnav_get_number_of_titles(priv->dvdnav, &titles);
- for(i=0; i<titles; i++)
+ for(i=1; i<=titles; i++)
identify_chapters(priv->dvdnav, i);
}
else
@@ -600,6 +602,7 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(priv->dvdnav));
return STREAM_UNSUPPORTED;
}
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_CURRENT_TITLE=%d\n", p->track);
} else if (p->track == 0) {
if(dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root) != DVDNAV_STATUS_OK)
dvdnav_menu_call(priv->dvdnav, DVD_MENU_Title);
diff --git a/stream/stream_ffmpeg.c b/stream/stream_ffmpeg.c
index e6705883fc..343381afb0 100644
--- a/stream/stream_ffmpeg.c
+++ b/stream/stream_ffmpeg.c
@@ -34,6 +34,7 @@ static int fill_buffer(stream_t *s, char *buffer, int max_len)
static int write_buffer(stream_t *s, char *buffer, int len)
{
+ /* url_write retries internally on short writes and EAGAIN */
int r = url_write(s->priv, buffer, len);
return (r <= 0) ? -1 : r;
}
diff --git a/stream/stream_file.c b/stream/stream_file.c
index 22be803fba..6d436cf6f5 100644
--- a/stream/stream_file.c
+++ b/stream/stream_file.c
@@ -56,8 +56,16 @@ static int fill_buffer(stream_t *s, char* buffer, int max_len){
}
static int write_buffer(stream_t *s, char* buffer, int len) {
- int r = write(s->fd,buffer,len);
- return (r <= 0) ? -1 : r;
+ int r;
+ int wr = 0;
+ while (wr < len) {
+ r = write(s->fd,buffer,len);
+ if (r <= 0)
+ return -1;
+ wr += r;
+ buffer += r;
+ }
+ return len;
}
static int seek(stream_t *s,off_t newpos) {
diff --git a/stream/stream_smb.c b/stream/stream_smb.c
index 14791a2995..f176bc7518 100644
--- a/stream/stream_smb.c
+++ b/stream/stream_smb.c
@@ -100,8 +100,16 @@ static int fill_buffer(stream_t *s, char* buffer, int max_len){
}
static int write_buffer(stream_t *s, char* buffer, int len) {
- int r = smbc_write(s->fd,buffer,len);
- return (r <= 0) ? -1 : r;
+ int r;
+ int wr = 0;
+ while (wr < len) {
+ r = smbc_write(s->fd,buffer,len);
+ if (r <= 0)
+ return -1;
+ wr += r;
+ buffer += r;
+ }
+ return len;
}
static void close_f(stream_t *s){