From 38202de4f953fca28aa884246ced0aadf0d25a4d Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 25 Jun 2021 12:44:53 +0200 Subject: Add a http server proxy for better youtube downloading (bypassing rate limit cased by http range header). Fix youtube live streams --- plugins/youtube/YoutubeMediaProxy.hpp | 100 ++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 plugins/youtube/YoutubeMediaProxy.hpp (limited to 'plugins/youtube') diff --git a/plugins/youtube/YoutubeMediaProxy.hpp b/plugins/youtube/YoutubeMediaProxy.hpp new file mode 100644 index 0000000..2d6ea93 --- /dev/null +++ b/plugins/youtube/YoutubeMediaProxy.hpp @@ -0,0 +1,100 @@ +#pragma once + +#include "../../include/Program.hpp" +#include + +// TODO: Sync sequence for video and audio (for live stream). + +namespace QuickMedia { + class YoutubeMediaProxy { + public: + enum Error { + OK, + ERROR + }; + + virtual ~YoutubeMediaProxy() = default; + + virtual bool start(const std::string &youtube_media_url, int content_length) = 0; + // This should be the last call. Do not call |start| after this. TODO: Allow restarting with |start| after |stop| is called. + virtual void stop() = 0; + virtual Error update() = 0; + virtual bool get_address(std::string &address) = 0; + + bool start_download(const std::string &media_url, ReadProgram &read_program, int range_start, bool include_header, bool is_livestream = false, int livestream_sequence = -1); + private: + int rn = 0; + int rbuf = 0; + }; + + class YoutubeStaticMediaProxy : public YoutubeMediaProxy { + public: + YoutubeStaticMediaProxy() = default; + YoutubeStaticMediaProxy(YoutubeStaticMediaProxy&) = delete; + YoutubeStaticMediaProxy&operator=(YoutubeStaticMediaProxy&) = delete; + ~YoutubeStaticMediaProxy(); + + bool start(const std::string &youtube_media_url, int content_length) override; + void stop() override; + Error update() override; + bool get_address(std::string &address) override; + private: + void on_client_disconnect(); + Error read_client_data(); + void clear_download_state(); + // If |new_range_start| is not -1 then the start range is set to that + Error update_download_program_status(bool client_disconnected, int new_range_start = -1, bool restart_download = false); + Error continue_send(const char *buffer_start, size_t total_bytes_to_write, int &buffer_offset); + Error handle_download(); + // Returns the client fd or -1 + int accept_client(); + private: + int socket_fd = -1; + int port = 0; + int client_fd = -1; + std::string youtube_media_url; + int content_length = 0; + ReadProgram downloader_read_program; + int download_read_buffer_offset = 0; + ssize_t downloader_num_read_bytes = 0; + int download_range_start = 0; + int current_download_range = 0; + std::string download_header; + bool download_header_finished = false; + bool download_header_sent = false; + bool download_header_remaining_sent = false; + int download_header_written_offset = 0; + int download_header_offset_to_end_of_header = 0; + bool client_request_finished = false; + std::string client_request_buffer; + char download_read_buffer[16384]; + }; + + class YoutubeLiveStreamMediaProxy : public YoutubeMediaProxy { + public: + YoutubeLiveStreamMediaProxy() = default; + YoutubeLiveStreamMediaProxy(YoutubeLiveStreamMediaProxy&) = delete; + YoutubeLiveStreamMediaProxy&operator=(YoutubeLiveStreamMediaProxy&) = delete; + ~YoutubeLiveStreamMediaProxy(); + + bool start(const std::string &youtube_media_url, int content_length) override; + void stop() override; + Error update() override; + bool get_address(std::string &address) override; + private: + Error update_download_program_status(); + Error continue_send(const char *buffer_start, size_t total_bytes_to_write, int &buffer_offset); + private: + ReadProgram downloader_read_program; + std::string youtube_media_url; + int fd[2]; + int livestream_sequence_num = -1; + std::string download_header; + bool download_header_finished = false; + bool download_header_remaining_sent = false; + int download_header_written_offset = 0; + int download_read_buffer_offset = 0; + ssize_t downloader_num_read_bytes = 0; + char download_read_buffer[16384]; + }; +} \ No newline at end of file -- cgit v1.2.3