aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-08-05 10:22:41 +0200
committerdec05eba <dec05eba@protonmail.com>2021-08-05 10:29:32 +0200
commita0c0f0bd551155270b11ac23c7f1c526a20a44b9 (patch)
tree5058c250fce097684d75aa900d060c9d1519b591 /src/plugins
parent6c85194c3b1baef0eaa011c4f1b8e48e11860f45 (diff)
Youtube: attempt to auto-detect throttling and restart download
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/youtube/YoutubeMediaProxy.cpp57
1 files changed, 53 insertions, 4 deletions
diff --git a/src/plugins/youtube/YoutubeMediaProxy.cpp b/src/plugins/youtube/YoutubeMediaProxy.cpp
index 6642b86..ed38981 100644
--- a/src/plugins/youtube/YoutubeMediaProxy.cpp
+++ b/src/plugins/youtube/YoutubeMediaProxy.cpp
@@ -19,6 +19,8 @@
namespace QuickMedia {
static const int MAX_BUFFER_SIZE = 65536;
static const int RANGE = 524287;
+ static const int64_t THROTTLED_DOWNLOAD_LIMIT_KB = 80; // TODO: What about people with really slow internet? What if the video player cache is not working and download is stuck, leading to false download speed calculation?
+ static const int64_t THROTTLED_DURATION_SECS = 3;
static const char download_error_response_msg[] =
"HTTP/1.1 500 Internal Server Error\r\n"
"Content-Length: 0\r\n\r\n";
@@ -73,6 +75,10 @@ namespace QuickMedia {
return true;
}
+ YoutubeStaticMediaProxy::YoutubeStaticMediaProxy(ThrottleHandler throttle_handler) : throttle_handler(std::move(throttle_handler)) {
+
+ }
+
YoutubeStaticMediaProxy::~YoutubeStaticMediaProxy() {
stop();
}
@@ -193,6 +199,8 @@ namespace QuickMedia {
void YoutubeStaticMediaProxy::on_client_disconnect() {
client_request_buffer.clear();
client_request_finished = false;
+ download_started = false;
+ throttle_started = false;
if(client_fd != -1) {
close(client_fd);
@@ -248,6 +256,8 @@ namespace QuickMedia {
if(header_end != std::string::npos) {
client_request_buffer.erase(header_end + 4);
client_request_finished = true;
+ download_started = false;
+ throttle_started = false;
int new_start_range = header_extract_start_range(client_request_buffer);
//fprintf(stderr, "got new range from client: %d\n", new_start_range);
@@ -284,7 +294,7 @@ namespace QuickMedia {
if(client_disconnected) {
wait_program(downloader_read_program.pid);
} else {
- if(wait_program_non_blocking(downloader_read_program.pid, &program_status) == 0)
+ if(wait_program_non_blocking(downloader_read_program.pid, &program_status) == 0 && program_status == 0)
return Error::OK;
}
downloader_read_program.pid = -1;
@@ -444,6 +454,45 @@ namespace QuickMedia {
Error err = update_download_program_status(false, -1, true);
if(err != Error::OK)
return err;
+ } else {
+ if(!download_started) {
+ total_downloaded_bytes = 0;
+ download_started = true;
+ throttle_started = false;
+
+ struct timespec tp;
+ clock_gettime(CLOCK_BOOTTIME, &tp);
+ download_start_time = tp.tv_sec;
+ }
+ total_downloaded_bytes += downloader_num_read_bytes;
+ }
+ }
+
+ if(download_started) {
+ struct timespec tp;
+ clock_gettime(CLOCK_BOOTTIME, &tp);
+
+ int64_t time_elapsed = tp.tv_sec - download_start_time;
+ int64_t download_speed_kb_sec = 0;
+ if(time_elapsed > 0)
+ download_speed_kb_sec = (total_downloaded_bytes / time_elapsed) / 1024;
+
+ if(download_speed_kb_sec < THROTTLED_DOWNLOAD_LIMIT_KB) {
+ if(throttle_started) {
+ if(tp.tv_sec - throttle_start_time >= THROTTLED_DURATION_SECS && !throttle_callback_called) {
+ total_downloaded_bytes = 0;
+ download_started = false;
+ throttle_started = false;
+ throttle_callback_called = true;
+ if(throttle_handler)
+ throttle_handler();
+ }
+ } else {
+ throttle_started = true;
+ throttle_start_time = tp.tv_sec;
+ }
+ } else {
+ throttle_started = false;
}
}
@@ -587,7 +636,7 @@ namespace QuickMedia {
YoutubeMediaProxy::Error YoutubeLiveStreamMediaProxy::update_download_program_status() {
int program_status = 0;
- if(wait_program_non_blocking(downloader_read_program.pid, &program_status) == 0)
+ if(wait_program_non_blocking(downloader_read_program.pid, &program_status) == 0 && program_status == 0)
return Error::OK;
downloader_read_program.pid = -1;
@@ -688,13 +737,13 @@ namespace QuickMedia {
std::string sequence_num = header_extract_value(download_header, "x-sequence-num");
fprintf(stderr, "server sequence num: |%s|\n", sequence_num.c_str());
if(sequence_num.empty())
- fprintf(stderr, "YoutubeLiveStreamMediaProxy::handle_download: missing sequence num from server\n");
+ fprintf(stderr, "YoutubeLiveStreamMediaProxy::update: missing sequence num from server\n");
else
livestream_sequence_num = strtoll(sequence_num.c_str(), nullptr, 10);
}
} else {
if(download_header.size() > MAX_BUFFER_SIZE) {
- fprintf(stderr, "YoutubeLiveStreamMediaProxy::handle_download: buffer is full (malicious server?)\n");
+ fprintf(stderr, "YoutubeLiveStreamMediaProxy::update: buffer is full (malicious server?)\n");
if(downloader_read_program.pid != -1) {
kill(downloader_read_program.pid, SIGTERM);
wait_program(downloader_read_program.pid);