From 36b9879c769bcbc46df23b995435a8e5d2dbd43f Mon Sep 17 00:00:00 2001 From: QCFium Date: Sat, 27 Nov 2021 18:25:49 +0900 Subject: [PATCH] Fixed long loading when seeking near the end of the video --- source/network/network_decoder.cpp | 19 ++++++++++++++++--- source/network/network_decoder_multiple.cpp | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/source/network/network_decoder.cpp b/source/network/network_decoder.cpp index 21de96f5..0841abf7 100644 --- a/source/network/network_decoder.cpp +++ b/source/network/network_decoder.cpp @@ -764,9 +764,17 @@ Result_with_string NetworkDecoder::seek(s64 microseconds) { clear_buffer(); + s64 min_ts = std::max(0, microseconds - 1000000); + s64 max_ts = microseconds + 500000; + if (video_audio_seperate) { - int ffmpeg_result = avformat_seek_file(format_context[VIDEO], -1, microseconds - 1000000, microseconds, microseconds + 1000000, AVSEEK_FLAG_FRAME); // AVSEEK_FLAG_FRAME <- ? - if(ffmpeg_result < 0) { + int ffmpeg_result = avformat_seek_file(format_context[VIDEO], -1, min_ts, microseconds, max_ts, AVSEEK_FLAG_FRAME); // AVSEEK_FLAG_FRAME <- ? + for (int i = 2; i <= 3 && ffmpeg_result < 0; i++) { // retry with wider range backward + min_ts = std::max(0, microseconds - i * 1000000); + ffmpeg_result = avformat_seek_file(format_context[VIDEO], -1, min_ts, microseconds, max_ts, AVSEEK_FLAG_FRAME); + if (ffmpeg_result >= 0) Util_log_save("seek", "succeeded at " + std::to_string(ffmpeg_result)); + } + if (ffmpeg_result < 0) { result.code = DEF_ERR_FFMPEG_RETURNED_NOT_SUCCESS; result.string = DEF_ERR_FFMPEG_RETURNED_NOT_SUCCESS_STR; result.error_description = "avformat_seek_file() for video failed " + std::to_string(ffmpeg_result); @@ -794,7 +802,12 @@ Result_with_string NetworkDecoder::seek(s64 microseconds) { if (result.code != 0) return result; return result; } else { - int ffmpeg_result = avformat_seek_file(format_context[BOTH], -1, microseconds - 1000000, microseconds, microseconds + 1000000, AVSEEK_FLAG_FRAME); // AVSEEK_FLAG_FRAME <- ? + int ffmpeg_result = avformat_seek_file(format_context[BOTH], -1, min_ts, microseconds, max_ts, AVSEEK_FLAG_FRAME); // AVSEEK_FLAG_FRAME <- ? + for (int i = 2; i <= 3 && ffmpeg_result < 0; i++) { // retry with wider range backward + min_ts = std::max(0, microseconds - i * 1000000); + ffmpeg_result = avformat_seek_file(format_context[BOTH], -1, min_ts, microseconds, max_ts, AVSEEK_FLAG_FRAME); + if (ffmpeg_result >= 0) Util_log_save("seek", "succeeded at " + std::to_string(ffmpeg_result)); + } if(ffmpeg_result < 0) { result.code = DEF_ERR_FFMPEG_RETURNED_NOT_SUCCESS; result.string = DEF_ERR_FFMPEG_RETURNED_NOT_SUCCESS_STR; diff --git a/source/network/network_decoder_multiple.cpp b/source/network/network_decoder_multiple.cpp index 9ae02db7..f2408f81 100644 --- a/source/network/network_decoder_multiple.cpp +++ b/source/network/network_decoder_multiple.cpp @@ -215,7 +215,7 @@ Result_with_string NetworkMultipleDecoder::seek(s64 microseconds) { decoder.clear_buffer(); decoder.change_ffmpeg_data(fragments[(int) seq_using], adjust_timestamp ? seq_using * fragment_len : 0); // trying to seek to a point too close to the end somehow causes ffmpeg to read the entire stream again ? - microseconds = std::max(0.0, std::min((double) microseconds, (get_duration() - 2) * 1000000)); + microseconds = std::max(0.0, std::min((double) microseconds, (get_duration() - 1) * 1000000)); result = decoder.seek(microseconds); } return result;