Skip to content

Commit

Permalink
feat: added a progress bar for CLI
Browse files Browse the repository at this point in the history
Signed-off-by: k4yt3x <i@k4yt3x.com>
  • Loading branch information
k4yt3x committed Oct 9, 2024
1 parent ec4fc0e commit b230010
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 19 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
project(video2x VERSION 6.0.0 LANGUAGES CXX C)

# Set the C standard
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

# Set the C++ standard
Expand Down
4 changes: 3 additions & 1 deletion include/libvideo2x.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef LIBVIDEO2X_H
#define LIBVIDEO2X_H

#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
Expand Down Expand Up @@ -65,9 +66,10 @@ struct EncoderConfig {

// Processing status
struct ProcessingStatus {
int64_t processed_frames;
atomic_int_fast64_t processed_frames;
int64_t total_frames;
time_t start_time;
bool completed;
};

// C-compatible process_video function
Expand Down
96 changes: 79 additions & 17 deletions src/video2x.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#include <libavutil/hwcontext.h>
#include <libavutil/pixdesc.h>
Expand Down Expand Up @@ -31,7 +32,7 @@ static struct option long_options[] = {
{"bitrate", required_argument, NULL, 'b'},
{"crf", required_argument, NULL, 'q'},

// Libplacebo options
// libplacebo options
{"shader", required_argument, NULL, 's'},
{"width", required_argument, NULL, 'w'},
{"height", required_argument, NULL, 'h'},
Expand Down Expand Up @@ -70,6 +71,14 @@ struct arguments {
int scaling_factor;
};

struct ProcessVideoThreadArguments {
struct arguments *arguments;
enum AVHWDeviceType hw_device_type;
struct FilterConfig *filter_config;
struct EncoderConfig *encoder_config;
struct ProcessingStatus *status;
};

const char *valid_models[] = {
"realesrgan-plus",
"realesrgan-plus-anime",
Expand Down Expand Up @@ -278,6 +287,32 @@ void parse_arguments(int argc, char **argv, struct arguments *arguments) {
}
}

// Wrapper function for video processing thread
int process_video_thread(void *arg) {
struct ProcessVideoThreadArguments *thread_args = (struct ProcessVideoThreadArguments *)arg;

// Extract individual arguments
struct arguments *arguments = thread_args->arguments;
enum AVHWDeviceType hw_device_type = thread_args->hw_device_type;
struct FilterConfig *filter_config = thread_args->filter_config;
struct EncoderConfig *encoder_config = thread_args->encoder_config;
struct ProcessingStatus *status = thread_args->status;

// Call the process_video function
int result = process_video(
arguments->input_filename,
arguments->output_filename,
arguments->benchmark,
hw_device_type,
filter_config,
encoder_config,
status
);

status->completed = true;
return result;
}

int main(int argc, char **argv) {
// Print help if no arguments are provided
if (argc < 2) {
Expand Down Expand Up @@ -348,41 +383,68 @@ int main(int argc, char **argv) {
}

// Setup struct to store processing status
struct ProcessingStatus status = {0};

// Process the video
if (process_video(
arguments.input_filename,
arguments.output_filename,
arguments.benchmark,
hw_device_type,
&filter_config,
&encoder_config,
&status
)) {
fprintf(stderr, "Video processing failed\n");
struct ProcessingStatus status = {
.processed_frames = 0, .total_frames = 0, .start_time = time(NULL), .completed = false
};

// Create a ThreadArguments struct to hold all the arguments for the thread
struct ProcessVideoThreadArguments thread_args = {
.arguments = &arguments,
.hw_device_type = hw_device_type,
.filter_config = &filter_config,
.encoder_config = &encoder_config,
.status = &status
};

// Create a thread for video processing
thrd_t processing_thread;
if (thrd_create(&processing_thread, process_video_thread, &thread_args) != thrd_success) {
fprintf(stderr, "Failed to create processing thread\n");
return 1;
}

// Main thread loop to display progress
while (!status.completed) {
printf(
"\r[Video2X] Processing frame %ld/%ld (%.2f%%); time elapsed: %lds",
atomic_load(&status.processed_frames),
status.total_frames,
status.processed_frames * 100.0 / status.total_frames,
time(NULL) - status.start_time
);
fflush(stdout);
thrd_sleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 100000000}, NULL);
}
puts(""); // Print newline after progress bar is complete

// Join the processing thread to ensure it completes before exiting
int process_result;
thrd_join(processing_thread, &process_result);

if (process_result != 0) {
fprintf(stderr, "Video processing failed\n");
return process_result;
}

// Calculate statistics
time_t time_elapsed = time(NULL) - status.start_time;
float speed_fps = (float)status.processed_frames / time_elapsed;
float average_speed_fps = (float)atomic_load(&status.processed_frames) / time_elapsed;

// Print processing summary
if (arguments.benchmark) {
printf("====== Video2X Benchmark summary ======\n");
printf("Video file processed: %s\n", arguments.input_filename);
printf("Total frames processed: %ld\n", status.processed_frames);
printf("Total time taken: %lds\n", time_elapsed);
printf("Average processing speed: %.2f FPS\n", speed_fps);
printf("Average processing speed: %.2f FPS\n", average_speed_fps);
return 0;
}

printf("====== Video2X Processing summary ======\n");
printf("Video file processed: %s\n", arguments.input_filename);
printf("Total frames processed: %ld\n", status.processed_frames);
printf("Total time taken: %lds\n", time_elapsed);
printf("Average processing speed: %.2f FPS\n", speed_fps);
printf("Average processing speed: %.2f FPS\n", average_speed_fps);
printf("Output written to: %s\n", arguments.output_filename);
return 0;
}

0 comments on commit b230010

Please sign in to comment.