diff options
Diffstat (limited to 'src/FileAnalyzer.cpp')
-rw-r--r-- | src/FileAnalyzer.cpp | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp index 361211f..61eff7b 100644 --- a/src/FileAnalyzer.cpp +++ b/src/FileAnalyzer.cpp @@ -21,10 +21,12 @@ namespace QuickMedia { // https://mimesniff.spec.whatwg.org/ // TODO: Test all of these - static const std::array<MagicNumber, 31> magic_numbers = { + static const std::array<MagicNumber, 33> magic_numbers = { MagicNumber{ {'R', 'I', 'F', 'F', -1, -1, -1, -1, 'A', 'V', 'I', ' '}, 12, ContentType::VIDEO_AVI }, MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm'}, 12, ContentType::VIDEO_MP4 }, + MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', 'i', 's', 'o', '5'}, 12, ContentType::VIDEO_MP4 }, MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', 'm', 'p', '4', '2'}, 12, ContentType::VIDEO_MP4 }, + MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', 'M', '4', 'V'}, 11, ContentType::VIDEO_MP4 }, MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', '3', 'g', 'p', '4'}, 12, ContentType::VIDEO_MP4 }, MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', '3', 'g', 'p', '5'}, 12, ContentType::VIDEO_MP4 }, MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'm', 'p', '4', '2'}, 11, ContentType::VIDEO_MP4 }, @@ -136,29 +138,29 @@ namespace QuickMedia { || strcase_equals(ext, ".wav") || strcase_equals(ext, ".wma") || strcase_equals(ext, ".mid"); - } - bool video_get_middle_frame(const FileAnalyzer &file, const char *destination_path, int width, int height) { + bool video_get_frame(const FileAnalyzer &file, const char *destination_path, int width, int height, int seconds) { Path destination_path_tmp = destination_path; destination_path_tmp.append(".tmp.jpg"); // TODO: .png, but the below code also needs to be changed for that - const int middle_seconds = file.get_duration_seconds().value_or(0.0) / 2.0; - char middle_seconds_str[32]; - snprintf(middle_seconds_str, sizeof(middle_seconds_str), "%d", middle_seconds); + char seconds_str[32]; + snprintf(seconds_str, sizeof(seconds_str), "%d", seconds); + + int allowed_exit_status[] = { 0, 69 }; if(width > 0 && height > 0) { char size_arg_str[512]; snprintf(size_arg_str, sizeof(size_arg_str), "scale=%d:%d:force_original_aspect_ratio=decrease", width, height); - const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-ss", middle_seconds_str, "-i", file.get_filepath().c_str(), "-vframes", "1", "-vf", size_arg_str, "--", destination_path_tmp.data.c_str(), nullptr }; - if(exec_program(program_args, nullptr, nullptr) != 0) { + const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-ss", seconds_str, "-i", file.get_filepath().c_str(), "-frames:v", "1", "-vf", size_arg_str, "--", destination_path_tmp.data.c_str(), nullptr }; + if(exec_program(program_args, nullptr, nullptr, allowed_exit_status, 2) != 0) { fprintf(stderr, "Failed to execute ffmpeg, maybe its not installed?\n"); return false; } } else { - const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-ss", middle_seconds_str, "-i", file.get_filepath().c_str(), "-vframes", "1", "--", destination_path_tmp.data.c_str(), nullptr }; - if(exec_program(program_args, nullptr, nullptr) != 0) { + const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-ss", seconds_str, "-i", file.get_filepath().c_str(), "-frames:v", "1", "--", destination_path_tmp.data.c_str(), nullptr }; + if(exec_program(program_args, nullptr, nullptr, allowed_exit_status, 2) != 0) { fprintf(stderr, "Failed to execute ffmpeg, maybe its not installed?\n"); return false; } @@ -167,6 +169,16 @@ namespace QuickMedia { return rename_atomic(destination_path_tmp.data.c_str(), destination_path) == 0; } + bool video_get_start_frame(const FileAnalyzer &file, const char *destination_path, int width, int height) { + const int start_seconds = std::max(0.0, std::min(3.0, file.get_duration_seconds().value_or(0.0) - 1.0)); + return video_get_frame(file, destination_path, width, height, start_seconds); + } + + bool video_get_middle_frame(const FileAnalyzer &file, const char *destination_path, int width, int height) { + const int middle_seconds = file.get_duration_seconds().value_or(0.0) / 2.0; + return video_get_frame(file, destination_path, width, height, middle_seconds); + } + // TODO: Remove dependency on ffprobe static bool ffprobe_extract_metadata(const char *filepath, std::optional<Dimensions> &dimensions, std::optional<double> &duration_seconds) { const char *program_args[] = { "ffprobe", "-v", "quiet", "-print_format", "json", "-show_streams", "-show_format", "--", filepath, nullptr }; |