From d92f6d7725720e3facf90b0fdefc1ef4eb1c2227 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 11 Mar 2022 10:45:01 +0100 Subject: youtube video: fix video with redirect not getting content length correctly, re-enable youtube timestamp --- TODO | 1 - src/Downloader.cpp | 19 ++++++++++++++----- src/plugins/Youtube.cpp | 4 ---- video_player/src/main.cpp | 47 +++++++++++++++++++++++++++++++++++++---------- 4 files changed, 51 insertions(+), 20 deletions(-) diff --git a/TODO b/TODO index d8408a0..a530f0e 100644 --- a/TODO +++ b/TODO @@ -223,5 +223,4 @@ Zero clear password memory after use. Periodically cleanup old cache files (especially manga images, thumbnails and media). Maybe have a file that says when we last checked for old files, and if its X days old then check and remove old files again and update the file. Render watch progress in youtube. -Readd youtube watch progress which seems to be broken because of frozen download? Set _NET_WM_USER_TIME (see sfml). \ No newline at end of file diff --git a/src/Downloader.cpp b/src/Downloader.cpp index cb9f448..57a0349 100644 --- a/src/Downloader.cpp +++ b/src/Downloader.cpp @@ -310,8 +310,20 @@ namespace QuickMedia { return offset; } + static ssize_t read_eintr(int fd, void *buffer, size_t size) { + while(true) { + ssize_t bytes_read = read(fd, buffer, size); + if(bytes_read == -1) { + if(errno != EINTR) + return -1; + } else { + return bytes_read; + } + } + } + static int64_t read_fn(YoutubeReadProgram *program, char *buf, uint64_t nbytes) { - ssize_t bytes_read = read(program->read_program.read_fd, buf, nbytes); + ssize_t bytes_read = read_eintr(program->read_program.read_fd, buf, nbytes); if(bytes_read > 0) { program->offset += bytes_read; program->bytes_downloaded += bytes_read; @@ -319,15 +331,12 @@ namespace QuickMedia { // End of current range, progress to next range bytes_read = seek_fn(program, program->offset); if(bytes_read >= 0) { - bytes_read = read(program->read_program.read_fd, buf, nbytes); + bytes_read = read_eintr(program->read_program.read_fd, buf, nbytes); if(bytes_read > 0) { program->offset += bytes_read; program->bytes_downloaded += bytes_read; } } - } else if(bytes_read < 0) { - if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) - return 0; } return bytes_read; } diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index df79701..2d92cd8 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -1860,7 +1860,6 @@ namespace QuickMedia { } std::string YoutubeVideoPage::get_url_timestamp() { - #if 0 if(!timestamp.empty()) return timestamp; @@ -1882,9 +1881,6 @@ namespace QuickMedia { return ""; else return std::to_string(it->second.time_pos_sec); - #else - return timestamp; - #endif } BodyItems YoutubeVideoPage::get_related_media(const std::string &url) { diff --git a/video_player/src/main.cpp b/video_player/src/main.cpp index 42a9b4f..4ec9278 100644 --- a/video_player/src/main.cpp +++ b/video_player/src/main.cpp @@ -409,7 +409,7 @@ static int64_t size_fn(void *cookie) { buffer.resize(8192); size_t read_offset = 0; for(;;) { - ssize_t bytes_read = read(header_program.read_fd, &buffer[read_offset], buffer.size() - read_offset); + ssize_t bytes_read = read_eintr(header_program.read_fd, &buffer[read_offset], buffer.size() - read_offset); if(bytes_read == 0) { buffer.resize(read_offset); break; @@ -448,26 +448,36 @@ static int64_t size_fn(void *cookie) { close(header_program.read_fd); if(res == 0) { - size_t content_length_index = str_find_case_insensitive(buffer, 0, "content-length:", 15); + size_t header_start = str_find_case_insensitive(buffer, 0, "200 OK", 6); + if(header_start == std::string::npos) + goto end; + + header_start += 6; + size_t content_length_index = str_find_case_insensitive(buffer, header_start, "content-length:", 15); if(content_length_index == std::string::npos) - return res; + goto end; content_length_index += 15; size_t content_length_end = buffer.find('\r', content_length_index); if(content_length_end == std::string::npos) - return res; + goto end; buffer[content_length_end] = '\0'; errno = 0; char *endptr; int64_t content_length = strtoll(&buffer[content_length_index], &endptr, 10); if(endptr == &buffer[content_length_index] || errno != 0) - return res; + goto end; res = content_length; } + end: program->content_length = res; + if(res < 0) { + fprintf(stderr, "Error: video size failed\n"); + exit(2); + } return res; } @@ -497,26 +507,32 @@ static int64_t seek_fn(void *cookie, int64_t offset) { "-g", "-s", "-L", "-f", "-r", range, "--", program->url, nullptr }; int res = exec_program_pipe(args, program); - if(res != 0) - return MPV_ERROR_GENERIC; + if(res != 0) { + fprintf(stderr, "Error: video seek failed\n"); + exit(2); + } return offset; } static int64_t read_fn(void *cookie, char *buf, uint64_t nbytes) { ReadProgram *program = (ReadProgram*)cookie; - ssize_t bytes_read = read(program->read_fd, buf, nbytes); + ssize_t bytes_read = read_eintr(program->read_fd, buf, nbytes); if(bytes_read > 0) { program->offset += bytes_read; } else if(bytes_read == 0) { // End of current range, progress to next range bytes_read = seek_fn(program, program->offset); if(bytes_read >= 0) { - bytes_read = read(program->read_fd, buf, nbytes); + bytes_read = read_eintr(program->read_fd, buf, nbytes); if(bytes_read > 0) program->offset += bytes_read; } } + if(bytes_read < 0) { + fprintf(stderr, "Error: video read failed\n"); + exit(2); + } return bytes_read; } @@ -550,6 +566,10 @@ static int open_fn(void*, char *uri, mpv_stream_cb_info *info) { read_program->url = strdup((const char*)uri + 8); read_program->offset = 0; int64_t res = seek_fn(read_program, read_program->offset); + if(res < 0) { + fprintf(stderr, "Error: video open failed\n"); + exit(2); + } info->cookie = read_program; info->size_fn = size_fn; @@ -601,6 +621,7 @@ int main(int argc, char **argv) { std::string json_errors; bool file_started = false; + int exit_code = 0; while (running) { mpv_event *event = mpv_wait_event(mpv_ctx, -1.0); @@ -613,6 +634,12 @@ int main(int argc, char **argv) { } else if(event->event_id == MPV_EVENT_SHUTDOWN) { running = false; break; + } else if(event->event_id == MPV_EVENT_END_FILE) { + mpv_event_end_file *end_file_event = (mpv_event_end_file*)event->data; + if(end_file_event->error == MPV_END_FILE_REASON_ERROR) { + exit_code = 2; + break; + } } else if(event->event_id == MPV_EVENT_PROPERTY_CHANGE) { // End of file (idle) mpv_event_property *property = (mpv_event_property*)event->data; @@ -637,5 +664,5 @@ int main(int argc, char **argv) { } mpv_terminate_destroy(mpv_ctx); - return 0; + return exit_code; } -- cgit v1.2.3