summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stream/stream.c27
-rw-r--r--stream/stream.h10
2 files changed, 33 insertions, 4 deletions
diff --git a/stream/stream.c b/stream/stream.c
index 3bfa418c90..60b3571b82 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -52,6 +52,9 @@
#include "core/m_option.h"
#include "core/m_struct.h"
+// Includes additional padding in case sizes get rounded up by sector size.
+#define TOTAL_BUFFER_SIZE (STREAM_MAX_BUFFER_SIZE + STREAM_MAX_SECTOR_SIZE)
+
/// We keep these 2 for the gui atm, but they will be removed.
char *cdrom_device = NULL;
char *dvd_device = NULL;
@@ -352,6 +355,7 @@ void stream_capture_write(stream_t *s)
int stream_read_unbuffered(stream_t *s, void *buf, int len)
{
int orig_len = len;
+ s->buf_pos = s->buf_len = 0;
// we will retry even if we already reached EOF previously.
switch (s->type) {
case STREAMTYPE_STREAM:
@@ -396,6 +400,26 @@ eof_out:
return len;
}
+// This works like stdio's ungetc(), but for more than one byte. Rewind the
+// file position by buffer_size, and make all future reads/buffer fills read
+// from the given buffer, until the buffer is exhausted or a seek outside of
+// the buffer happens.
+// You can unread at most STREAM_MAX_BUFFER_SIZE bytes.
+void stream_unread_buffer(stream_t *s, void *buffer, size_t buffer_size)
+{
+ assert(stream_tell(s) >= buffer_size); // can't unread to before file start
+ assert(buffer_size <= STREAM_MAX_BUFFER_SIZE);
+ // Need to include the remaining buffer to ensure no data is lost.
+ int remainder = s->buf_len - s->buf_pos;
+ // Successive buffer unreading might trigger this.
+ assert(buffer_size + remainder <= TOTAL_BUFFER_SIZE);
+ memmove(&s->buffer[buffer_size], &s->buffer[s->buf_pos], remainder);
+ memcpy(s->buffer, buffer, buffer_size);
+ s->buf_pos = 0;
+ s->buf_len = buffer_size + remainder;
+ s->eof = 0;
+}
+
int stream_fill_buffer(stream_t *s)
{
int len = stream_read_unbuffered(s, s->buffer, STREAM_BUFFER_SIZE);
@@ -625,7 +649,8 @@ void stream_update_size(stream_t *s)
static stream_t *new_stream(void)
{
- stream_t *s = talloc_zero(NULL, stream_t);
+ stream_t *s = talloc_size(NULL, sizeof(stream_t) + TOTAL_BUFFER_SIZE);
+ memset(s, 0, sizeof(stream_t));
#if HAVE_WINSOCK2_H
{
diff --git a/stream/stream.h b/stream/stream.h
index 43ed6280bf..12ef430b28 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -58,6 +58,9 @@
#define STREAM_BUFFER_SIZE 2048
#define STREAM_MAX_SECTOR_SIZE (8 * 1024)
+// Max buffer for initial probe.
+#define STREAM_MAX_BUFFER_SIZE (2 * 1024 * 1024)
+
/// atm it will always use mode == STREAM_READ
/// streams that use the new api should check the mode at open
#define STREAM_READ 0
@@ -184,14 +187,14 @@ typedef struct stream {
char *lavf_type; // name of expected demuxer type for lavf
struct MPOpts *opts;
streaming_ctrl_t *streaming_ctrl;
- unsigned char buffer[STREAM_BUFFER_SIZE >
- STREAM_MAX_SECTOR_SIZE ? STREAM_BUFFER_SIZE :
- STREAM_MAX_SECTOR_SIZE];
FILE *capture_file;
char *capture_filename;
struct stream *uncached_stream;
+
+ // Includes additional padding in case sizes get rounded up by sector size.
+ unsigned char buffer[];
} stream_t;
#ifdef CONFIG_NETWORKING
@@ -199,6 +202,7 @@ typedef struct stream {
#endif
int stream_fill_buffer(stream_t *s);
+void stream_unread_buffer(stream_t *s, void *buffer, size_t buffer_size);
void stream_set_capture_file(stream_t *s, const char *filename);
void stream_capture_write(stream_t *s);