diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d0035b..b1078c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,12 +309,13 @@ list(REMOVE_DUPLICATES ALL_LIBRARIES) # Create the shared library 'libvideo2x' add_library(libvideo2x + src/avutils.cpp src/conversions.cpp src/decoder.cpp src/encoder.cpp src/fsutils.cpp - src/libplacebo_filter.cpp src/libplacebo.cpp + src/libplacebo_filter.cpp src/libvideo2x.cpp src/realesrgan_filter.cpp ) diff --git a/include/libvideo2x/avutils.h b/include/libvideo2x/avutils.h new file mode 100644 index 0000000..2135e2f --- /dev/null +++ b/include/libvideo2x/avutils.h @@ -0,0 +1,10 @@ +#ifndef AVUTILS_H +#define AVUTILS_H + +extern "C" { +#include +} + +int64_t get_video_frame_count(AVFormatContext *ifmt_ctx, int in_vstream_idx); + +#endif // AVUTILS_H diff --git a/src/avutils.cpp b/src/avutils.cpp new file mode 100644 index 0000000..b036f0b --- /dev/null +++ b/src/avutils.cpp @@ -0,0 +1,50 @@ +#include "avutils.h" + +#include + +int64_t get_video_frame_count(AVFormatContext *ifmt_ctx, int in_vstream_idx) { + // Use the 'nb_frames' field if it is available + int64_t nb_frames = ifmt_ctx->streams[in_vstream_idx]->nb_frames; + if (nb_frames != AV_NOPTS_VALUE && nb_frames > 0) { + spdlog::debug("Read total number of frames from 'nb_frames': {}", nb_frames); + return nb_frames; + } + spdlog::warn("Estimating the total number of frames from duration * fps"); + + // Get the duration of the video + double duration_secs = 0.0; + if (ifmt_ctx->duration != AV_NOPTS_VALUE) { + duration_secs = static_cast(ifmt_ctx->duration) / static_cast(AV_TIME_BASE); + } else if (ifmt_ctx->streams[in_vstream_idx]->duration != AV_NOPTS_VALUE) { + duration_secs = static_cast(ifmt_ctx->streams[in_vstream_idx]->duration) * + av_q2d(ifmt_ctx->streams[in_vstream_idx]->time_base); + } + if (duration_secs <= 0) { + spdlog::warn("Unable to determine the video's duration"); + return -1; + } + spdlog::debug("Video duration: {}s", duration_secs); + + // Calculate average FPS + double fps = av_q2d(ifmt_ctx->streams[in_vstream_idx]->avg_frame_rate); + if (fps <= 0) { + spdlog::debug("Unable to read the average frame rate from 'avg_frame_rate'"); + fps = av_q2d(ifmt_ctx->streams[in_vstream_idx]->r_frame_rate); + } + if (fps <= 0) { + spdlog::debug("Unable to read the average frame rate from 'r_frame_rate'"); + fps = av_q2d(av_guess_frame_rate(ifmt_ctx, ifmt_ctx->streams[in_vstream_idx], nullptr)); + } + if (fps <= 0) { + spdlog::debug("Unable to estimate the average frame rate with 'av_guess_frame_rate'"); + fps = av_q2d(ifmt_ctx->streams[in_vstream_idx]->time_base); + } + if (fps <= 0) { + spdlog::warn("Unable to estimate the video's average frame rate"); + return -1; + } + spdlog::debug("Video average frame rate: {}", fps); + + // Estimate and return the total number of frames + return static_cast(duration_secs * fps); +} diff --git a/src/libvideo2x.cpp b/src/libvideo2x.cpp index 9e4aff2..f9f70f0 100644 --- a/src/libvideo2x.cpp +++ b/src/libvideo2x.cpp @@ -11,6 +11,7 @@ extern "C" { #include +#include "avutils.h" #include "decoder.h" #include "encoder.h" #include "filter.h" @@ -37,46 +38,7 @@ static int process_frames( // Get the total number of frames in the video with OpenCV spdlog::debug("Reading total number of frames"); - proc_ctx->total_frames = ifmt_ctx->streams[in_vstream_idx]->nb_frames; - if (proc_ctx->total_frames > 0) { - spdlog::debug("Read total number of frames from 'nb_frames': {}", proc_ctx->total_frames); - } else { - spdlog::warn("Estimating the total number of frames from duration * fps"); - - // Get the duration of the video - double duration_secs = 0.0; - if (ifmt_ctx->duration != AV_NOPTS_VALUE) { - duration_secs = - static_cast(ifmt_ctx->duration) / static_cast(AV_TIME_BASE); - } else if (ifmt_ctx->streams[in_vstream_idx]->duration != AV_NOPTS_VALUE) { - duration_secs = static_cast(ifmt_ctx->streams[in_vstream_idx]->duration) * - av_q2d(ifmt_ctx->streams[in_vstream_idx]->time_base); - } else { - spdlog::warn("Unable to determine video duration"); - } - spdlog::debug("Video duration: {}s", duration_secs); - - // Calculate average FPS - double fps = av_q2d(ifmt_ctx->streams[in_vstream_idx]->avg_frame_rate); - if (fps <= 0) { - spdlog::debug("Unable to read the average frame rate from 'avg_frame_rate'"); - fps = av_q2d(ifmt_ctx->streams[in_vstream_idx]->r_frame_rate); - } - if (fps <= 0) { - spdlog::debug("Unable to read the average frame rate from 'r_frame_rate'"); - fps = av_q2d(av_guess_frame_rate(ifmt_ctx, ifmt_ctx->streams[in_vstream_idx], nullptr)); - } - if (fps <= 0) { - spdlog::debug("Unable to estimate the average frame rate with 'av_guess_frame_rate'"); - fps = av_q2d(ifmt_ctx->streams[in_vstream_idx]->time_base); - } - if (fps <= 0 || duration_secs <= 0) { - spdlog::warn("Unable to estimate the video's average frame rate"); - } else { - // Calculate total frames - proc_ctx->total_frames = static_cast(duration_secs * fps); - } - } + proc_ctx->total_frames = get_video_frame_count(ifmt_ctx, in_vstream_idx); // Check if the total number of frames is still 0 if (proc_ctx->total_frames <= 0) { diff --git a/src/video2x.cpp b/src/video2x.cpp index 4eacfae..e8fab95 100644 --- a/src/video2x.cpp +++ b/src/video2x.cpp @@ -676,7 +676,7 @@ int main(int argc, char **argv) { total_frames = proc_ctx.total_frames; pause = proc_ctx.pause; } - if (!pause && total_frames > 0) { + if (!pause && (total_frames > 0 || processed_frames > 0)) { double percentage = total_frames > 0 ? static_cast(processed_frames) * 100.0 / static_cast(total_frames) : 0.0;