| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
#ifdef HAVE_CONFIG_H |
|---|
| 23 |
# include "config.h" |
|---|
| 24 |
#endif |
|---|
| 25 |
|
|---|
| 26 |
#include <vlc_common.h> |
|---|
| 27 |
#include <vlc_plugin.h> |
|---|
| 28 |
|
|---|
| 29 |
#include <assert.h> |
|---|
| 30 |
#include <errno.h> |
|---|
| 31 |
|
|---|
| 32 |
#include <vlc_access.h> |
|---|
| 33 |
|
|---|
| 34 |
#define BANDWIDTH_TEXT N_("Bandwidth limit (bytes/s)") |
|---|
| 35 |
#define BANDWIDTH_LONGTEXT N_( \ |
|---|
| 36 |
"The bandwidth module will drop any data in excess of that many bytes " \ |
|---|
| 37 |
"per seconds." ) |
|---|
| 38 |
|
|---|
| 39 |
static int Open (vlc_object_t *); |
|---|
| 40 |
static void Close (vlc_object_t *); |
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 |
vlc_module_begin (); |
|---|
| 45 |
set_shortname (N_("Bandwidth")); |
|---|
| 46 |
set_description (N_("Bandwidth limiter")); |
|---|
| 47 |
set_category (CAT_INPUT); |
|---|
| 48 |
set_subcategory (SUBCAT_INPUT_ACCESS_FILTER); |
|---|
| 49 |
set_capability ("access_filter", 0); |
|---|
| 50 |
add_shortcut ("bandwidth"); |
|---|
| 51 |
set_callbacks (Open, Close); |
|---|
| 52 |
|
|---|
| 53 |
add_integer ("access-bandwidth", 65536, NULL, BANDWIDTH_TEXT, |
|---|
| 54 |
BANDWIDTH_LONGTEXT, false); |
|---|
| 55 |
vlc_module_end(); |
|---|
| 56 |
|
|---|
| 57 |
static ssize_t Read (access_t *access, uint8_t *buffer, size_t len); |
|---|
| 58 |
static int Seek (access_t *access, int64_t offset); |
|---|
| 59 |
static int Control (access_t *access, int cmd, va_list ap); |
|---|
| 60 |
|
|---|
| 61 |
struct access_sys_t |
|---|
| 62 |
{ |
|---|
| 63 |
mtime_t last_time; |
|---|
| 64 |
size_t last_size; |
|---|
| 65 |
size_t bandwidth; |
|---|
| 66 |
}; |
|---|
| 67 |
|
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 |
|
|---|
| 71 |
static int Open (vlc_object_t *obj) |
|---|
| 72 |
{ |
|---|
| 73 |
access_t *access = (access_t*)obj; |
|---|
| 74 |
access_t *src = access->p_source; |
|---|
| 75 |
|
|---|
| 76 |
if (src->pf_read != NULL) |
|---|
| 77 |
access->pf_read = Read; |
|---|
| 78 |
else |
|---|
| 79 |
{ |
|---|
| 80 |
msg_Err (obj, "block bandwidth limit not implemented"); |
|---|
| 81 |
return VLC_EGENERIC; |
|---|
| 82 |
} |
|---|
| 83 |
|
|---|
| 84 |
if (src->pf_seek != NULL) |
|---|
| 85 |
access->pf_seek = Seek; |
|---|
| 86 |
|
|---|
| 87 |
access->pf_control = Control; |
|---|
| 88 |
access->info = src->info; |
|---|
| 89 |
|
|---|
| 90 |
access_sys_t *p_sys = access->p_sys = malloc (sizeof (*p_sys)); |
|---|
| 91 |
if (p_sys == NULL) |
|---|
| 92 |
return VLC_ENOMEM; |
|---|
| 93 |
|
|---|
| 94 |
memset (p_sys, 0, sizeof (*p_sys)); |
|---|
| 95 |
p_sys->bandwidth = var_CreateGetInteger (access, "access-bandwidth"); |
|---|
| 96 |
p_sys->last_time = mdate (); |
|---|
| 97 |
|
|---|
| 98 |
msg_Dbg (obj, "bandwidth limit: %lu bytes/s", |
|---|
| 99 |
(unsigned long)p_sys->bandwidth); |
|---|
| 100 |
return VLC_SUCCESS; |
|---|
| 101 |
} |
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 |
static void Close (vlc_object_t *obj) |
|---|
| 108 |
{ |
|---|
| 109 |
access_t *access = (access_t *)obj; |
|---|
| 110 |
access_sys_t *p_sys = access->p_sys; |
|---|
| 111 |
free (p_sys); |
|---|
| 112 |
} |
|---|
| 113 |
|
|---|
| 114 |
|
|---|
| 115 |
static ssize_t Read (access_t *access, uint8_t *buffer, size_t len) |
|---|
| 116 |
{ |
|---|
| 117 |
access_t *src = access->p_source; |
|---|
| 118 |
access_sys_t *p_sys = access->p_sys; |
|---|
| 119 |
mtime_t now; |
|---|
| 120 |
|
|---|
| 121 |
if (len == 0) |
|---|
| 122 |
return 0; |
|---|
| 123 |
|
|---|
| 124 |
retry: |
|---|
| 125 |
now = mdate (); |
|---|
| 126 |
if (now <= p_sys->last_time) |
|---|
| 127 |
{ |
|---|
| 128 |
msg_Err (access, "*** ALERT *** System clock is going backward! ***"); |
|---|
| 129 |
return 0; |
|---|
| 130 |
} |
|---|
| 131 |
|
|---|
| 132 |
mtime_t delta = now - p_sys->last_time; |
|---|
| 133 |
p_sys->last_time = now; |
|---|
| 134 |
|
|---|
| 135 |
delta *= p_sys->bandwidth; |
|---|
| 136 |
delta /= 1000000u; |
|---|
| 137 |
|
|---|
| 138 |
if (delta == 0) |
|---|
| 139 |
{ |
|---|
| 140 |
now += 1000000u / p_sys->bandwidth; |
|---|
| 141 |
mwait (now); |
|---|
| 142 |
goto retry; |
|---|
| 143 |
} |
|---|
| 144 |
|
|---|
| 145 |
if (len > delta) |
|---|
| 146 |
{ |
|---|
| 147 |
msg_Dbg (access, "reading %"PRIu64" bytes instead of %zu", delta, |
|---|
| 148 |
len); |
|---|
| 149 |
len = (int)delta; |
|---|
| 150 |
} |
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 |
src->info.i_update = access->info.i_update; |
|---|
| 154 |
len = src->pf_read (src, buffer, len); |
|---|
| 155 |
access->info = src->info; |
|---|
| 156 |
|
|---|
| 157 |
msg_Dbg (access, "read %zu bytes", len); |
|---|
| 158 |
return len; |
|---|
| 159 |
} |
|---|
| 160 |
|
|---|
| 161 |
|
|---|
| 162 |
static int Control (access_t *access, int cmd, va_list ap) |
|---|
| 163 |
{ |
|---|
| 164 |
access_t *src = access->p_source; |
|---|
| 165 |
return src->pf_control (src, cmd, ap); |
|---|
| 166 |
} |
|---|
| 167 |
|
|---|
| 168 |
|
|---|
| 169 |
static int Seek (access_t *access, int64_t offset) |
|---|
| 170 |
{ |
|---|
| 171 |
access_t *src = access->p_source; |
|---|
| 172 |
|
|---|
| 173 |
src->info.i_update = access->info.i_update; |
|---|
| 174 |
int ret = src->pf_seek (src, offset); |
|---|
| 175 |
access->info = src->info; |
|---|
| 176 |
return ret; |
|---|
| 177 |
} |
|---|