From e2754bcd9002bbdc87de994783f235e5792780e6 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 23 May 2014 06:34:52 -0700 Subject: [PATCH] Make video providers report whether their file has audio tracks Fixes errors when trying to automatically open audio from dummy video and improves UX a little by disabling the Open Audio From Video menu item when there are no audio tracks. --- src/async_video_provider.h | 1 + src/command/audio.cpp | 3 ++- src/include/aegisub/video_provider.h | 3 +++ src/project.cpp | 3 ++- src/video_provider_avs.cpp | 24 +++++++++++------------- src/video_provider_cache.cpp | 2 ++ src/video_provider_ffmpegsource.cpp | 21 +++++++++++++-------- 7 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/async_video_provider.h b/src/async_video_provider.h index 317c8cabb..5da7e7ca1 100644 --- a/src/async_video_provider.h +++ b/src/async_video_provider.h @@ -111,6 +111,7 @@ public: std::string GetWarning() const { return source_provider->GetWarning(); } std::string GetDecoderName() const { return source_provider->GetDecoderName(); } bool ShouldSetVideoProperties() const { return source_provider->ShouldSetVideoProperties(); } + bool HasAudio() const { return source_provider->HasAudio(); } /// @brief Constructor /// @param videoFileName File to open diff --git a/src/command/audio.cpp b/src/command/audio.cpp index 66db86e66..6e860f0fc 100644 --- a/src/command/audio.cpp +++ b/src/command/audio.cpp @@ -32,6 +32,7 @@ #include "command.h" #include "../ass_dialogue.h" +#include "../async_video_provider.h" #include "../audio_box.h" #include "../audio_controller.h" #include "../audio_karaoke.h" @@ -118,7 +119,7 @@ struct audio_open_video final : public Command { CMD_TYPE(COMMAND_VALIDATE) bool Validate(const agi::Context *c) override { - return !c->project->VideoName().empty(); + return c->project->VideoProvider() && c->project->VideoProvider()->HasAudio(); } void operator()(agi::Context *c) override { diff --git a/src/include/aegisub/video_provider.h b/src/include/aegisub/video_provider.h index 509b7f8d8..e0f81a916 100644 --- a/src/include/aegisub/video_provider.h +++ b/src/include/aegisub/video_provider.h @@ -81,6 +81,9 @@ public: /// Should the video properties in the script be set to this video's property if they already have values? virtual bool ShouldSetVideoProperties() const { return true; } + + /// Does the file which this provider is reading have an audio track? + virtual bool HasAudio() const { return false; } }; DEFINE_BASE_EXCEPTION_NOINNER(VideoProviderError, agi::Exception) diff --git a/src/project.cpp b/src/project.cpp index 9cd1e3786..bb0356f49 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -295,8 +295,9 @@ bool Project::DoLoadVideo(agi::fs::path const& path) { } void Project::LoadVideo(agi::fs::path const& path) { + if (path.empty()) return; if (!DoLoadVideo(path)) return; - if (OPT_GET("Video/Open Audio")->GetBool() && audio_file != video_file) + if (OPT_GET("Video/Open Audio")->GetBool() && audio_file != video_file && video_provider->HasAudio()) DoLoadAudio(video_file, true); } diff --git a/src/video_provider_avs.cpp b/src/video_provider_avs.cpp index 71825a742..4dfb58d9f 100644 --- a/src/video_provider_avs.cpp +++ b/src/video_provider_avs.cpp @@ -27,11 +27,6 @@ // // Aegisub Project http://www.aegisub.org/ -/// @file video_provider_avs.cpp -/// @brief Avisynth-based video provider -/// @ingroup video_input -/// - #ifdef WITH_AVISYNTH #include "include/aegisub/video_provider.h" @@ -66,6 +61,7 @@ class AvisynthVideoProvider: public VideoProvider { std::string warning; std::string colorspace; std::string real_colorspace; + bool has_audio = false; AVSValue source_clip; PClip RGB32Video; @@ -84,16 +80,17 @@ public: try { Init(matrix); } catch (AvisynthError const&) { } } - int GetFrameCount() const override { return vi.num_frames; } - agi::vfr::Framerate GetFPS() const override { return fps; } - int GetWidth() const override { return vi.width; } - int GetHeight() const override { return vi.height; } - double GetDAR() const override { return 0; } + int GetFrameCount() const override { return vi.num_frames; } + agi::vfr::Framerate GetFPS() const override { return fps; } + int GetWidth() const override { return vi.width; } + int GetHeight() const override { return vi.height; } + double GetDAR() const override { return 0; } std::vector GetKeyFrames() const override { return keyframes; } - std::string GetWarning() const override { return warning; } - std::string GetDecoderName() const override { return decoder_name; } - std::string GetColorSpace() const override { return colorspace; } + std::string GetWarning() const override { return warning; } + std::string GetDecoderName() const override { return decoder_name; } + std::string GetColorSpace() const override { return colorspace; } std::string GetRealColorSpace() const override { return real_colorspace; } + bool HasAudio() const override { return has_audio; } }; AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) { @@ -189,6 +186,7 @@ file_exit: void AvisynthVideoProvider::Init(std::string const& colormatrix) { auto script = source_clip; vi = script.AsClip()->GetVideoInfo(); + has_audio = vi.HasAudio(); if (vi.IsRGB()) real_colorspace = colorspace = "None"; else { diff --git a/src/video_provider_cache.cpp b/src/video_provider_cache.cpp index 8e31540a4..58e2441dc 100644 --- a/src/video_provider_cache.cpp +++ b/src/video_provider_cache.cpp @@ -74,6 +74,8 @@ public: std::string GetDecoderName() const override { return master->GetDecoderName(); } std::string GetColorSpace() const override { return master->GetColorSpace(); } std::string GetRealColorSpace() const override { return master->GetRealColorSpace(); } + bool ShouldSetVideoProperties() const override { return master->ShouldSetVideoProperties(); } + bool HasAudio() const override { return master->HasAudio(); } }; std::shared_ptr VideoProviderCache::GetFrame(int n) { diff --git a/src/video_provider_ffmpegsource.cpp b/src/video_provider_ffmpegsource.cpp index b8384ed23..a3f307bbc 100644 --- a/src/video_provider_ffmpegsource.cpp +++ b/src/video_provider_ffmpegsource.cpp @@ -63,6 +63,7 @@ class FFmpegSourceVideoProvider final : public VideoProvider, FFmpegSourceProvid char FFMSErrMsg[1024]; ///< FFMS error message FFMS_ErrorInfo ErrInfo; ///< FFMS error codes/messages + bool has_audio = false; void LoadVideo(agi::fs::path const& filename, std::string const& colormatrix); @@ -84,16 +85,17 @@ public: #endif } - int GetFrameCount() const override { return VideoInfo->NumFrames; } - int GetWidth() const override { return Width; } - int GetHeight() const override { return Height; } - double GetDAR() const override { return DAR; } - agi::vfr::Framerate GetFPS() const override { return Timecodes; } - std::string GetColorSpace() const override { return ColorSpace; } + int GetFrameCount() const override { return VideoInfo->NumFrames; } + int GetWidth() const override { return Width; } + int GetHeight() const override { return Height; } + double GetDAR() const override { return DAR; } + agi::vfr::Framerate GetFPS() const override { return Timecodes; } + std::string GetColorSpace() const override { return ColorSpace; } std::string GetRealColorSpace() const override { return RealColorSpace; } std::vector GetKeyFrames() const override { return KeyFramesList; }; - std::string GetDecoderName() const override { return "FFmpegSource"; } - bool WantsCaching() const override { return true; } + std::string GetDecoderName() const override { return "FFmpegSource"; } + bool WantsCaching() const override { return true; } + bool HasAudio() const override { return has_audio; } }; std::string colormatrix_description(int cs, int cr) { @@ -204,6 +206,9 @@ void FFmpegSourceVideoProvider::LoadVideo(agi::fs::path const& filename, std::st throw VideoNotSupported(std::string("Couldn't find any video tracks: ") + ErrInfo.Buffer); } + // Check if there's an audio track + has_audio = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, nullptr) != -1; + // set thread count int Threads = OPT_GET("Provider/Video/FFmpegSource/Decoding Threads")->GetInt(); if (FFMS_GetVersion() < ((2 << 24) | (17 << 16) | (2 << 8) | 1) && FFMS_GetSourceType(Index) == FFMS_SOURCE_LAVF)