1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#pragma once
#include "../../include/Program.hpp"
#include <string>
#include <functional>
// TODO: Sync sequence for video and audio (for live stream).
namespace QuickMedia {
using ThrottleHandler = std::function<void()>;
class YoutubeMediaProxy {
public:
enum Error {
OK,
ERROR
};
virtual ~YoutubeMediaProxy() = default;
virtual bool start(const std::string &youtube_media_url, int64_t 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, int64_t 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(ThrottleHandler throttle_handler = nullptr);
YoutubeStaticMediaProxy(YoutubeStaticMediaProxy&) = delete;
YoutubeStaticMediaProxy&operator=(YoutubeStaticMediaProxy&) = delete;
~YoutubeStaticMediaProxy();
bool start(const std::string &youtube_media_url, int64_t 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, int64_t 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;
int64_t content_length = 0;
ReadProgram downloader_read_program;
int download_read_buffer_offset = 0;
ssize_t downloader_num_read_bytes = 0;
int64_t download_range_start = 0;
int64_t 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;
time_t download_start_time = 0;
time_t throttle_start_time = 0;
int64_t total_downloaded_bytes = 0;
bool download_started = false;
bool throttle_started = false;
bool throttle_callback_called = false;
ThrottleHandler throttle_handler = nullptr;
bool client_request_finished = false;
std::string client_request_buffer;
char download_read_buffer[16384];
};
// TODO: Add throttle detection for live streams
class YoutubeLiveStreamMediaProxy : public YoutubeMediaProxy {
public:
YoutubeLiveStreamMediaProxy() = default;
YoutubeLiveStreamMediaProxy(YoutubeLiveStreamMediaProxy&) = delete;
YoutubeLiveStreamMediaProxy&operator=(YoutubeLiveStreamMediaProxy&) = delete;
~YoutubeLiveStreamMediaProxy();
bool start(const std::string &youtube_media_url, int64_t 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];
int64_t 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];
};
}
|