diff --git a/build/Aegisub/Aegisub.vcxproj b/build/Aegisub/Aegisub.vcxproj
index c27d76d5a..c504b4202 100644
--- a/build/Aegisub/Aegisub.vcxproj
+++ b/build/Aegisub/Aegisub.vcxproj
@@ -243,12 +243,8 @@
-
-
-
-
diff --git a/build/Aegisub/Aegisub.vcxproj.filters b/build/Aegisub/Aegisub.vcxproj.filters
index 74d10b631..02e122708 100644
--- a/build/Aegisub/Aegisub.vcxproj.filters
+++ b/build/Aegisub/Aegisub.vcxproj.filters
@@ -390,21 +390,9 @@
Video\UI
-
- Video\Providers
-
-
- Video\Providers
-
-
- Video\Providers
-
Video\Providers
-
- Video\Providers
-
Video\Providers
diff --git a/src/dialog_video_details.cpp b/src/dialog_video_details.cpp
index 66796c07b..0a871a176 100644
--- a/src/dialog_video_details.cpp
+++ b/src/dialog_video_details.cpp
@@ -39,8 +39,8 @@
#include "ass_time.h"
#include "compat.h"
#include "include/aegisub/context.h"
+#include "include/aegisub/video_provider.h"
#include "video_context.h"
-#include "video_provider_manager.h"
#include
diff --git a/src/frame_main.cpp b/src/frame_main.cpp
index 4c262760f..49f6a23c8 100644
--- a/src/frame_main.cpp
+++ b/src/frame_main.cpp
@@ -44,6 +44,7 @@
#include "include/aegisub/menu.h"
#include "include/aegisub/toolbar.h"
#include "include/aegisub/hotkey.h"
+#include "include/aegisub/video_provider.h"
#include "ass_file.h"
#include "audio_controller.h"
@@ -69,7 +70,6 @@
#include "video_box.h"
#include "video_context.h"
#include "video_display.h"
-#include "video_provider_manager.h"
#include "video_slider.h"
#include
diff --git a/src/plugin_manager.cpp b/src/plugin_manager.cpp
index dad56f01d..7044e1ec5 100644
--- a/src/plugin_manager.cpp
+++ b/src/plugin_manager.cpp
@@ -38,13 +38,11 @@
#include "include/aegisub/spellchecker.h"
#include "include/aegisub/subtitles_provider.h"
#include "plugin_manager.h"
-#include "video_provider_manager.h"
#include "auto4_lua_factory.h"
#include
void RegisterBuiltInPlugins() {
- VideoProviderFactory::RegisterProviders();
AudioPlayerFactory::RegisterProviders();
SubtitlesProviderFactory::RegisterProviders();
SpellCheckerFactory::RegisterProviders();
diff --git a/src/threaded_frame_source.cpp b/src/threaded_frame_source.cpp
index 1334edaae..99f8850fb 100644
--- a/src/threaded_frame_source.cpp
+++ b/src/threaded_frame_source.cpp
@@ -25,6 +25,7 @@
#include "ass_file.h"
#include "export_fixstyle.h"
#include "include/aegisub/subtitles_provider.h"
+#include "include/aegisub/video_provider.h"
#include "video_frame.h"
#include "video_provider_manager.h"
diff --git a/src/video_provider_avs.cpp b/src/video_provider_avs.cpp
index 8c2777102..e9bd50ce5 100644
--- a/src/video_provider_avs.cpp
+++ b/src/video_provider_avs.cpp
@@ -35,7 +35,7 @@
#include "config.h"
#ifdef WITH_AVISYNTH
-#include "video_provider_avs.h"
+#include "include/aegisub/video_provider.h"
#include "options.h"
#include "video_frame.h"
@@ -45,6 +45,7 @@
#include
#include
#include
+#include
#include
#include
@@ -53,8 +54,42 @@
#include
#endif
-AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix)
-{
+#define VideoFrame AVSVideoFrame
+#include "avisynth.h"
+#undef VideoFrame
+#include "avisynth_wrap.h"
+
+namespace {
+class AvisynthVideoProvider: public VideoProvider {
+ AviSynthWrapper avs;
+ std::string decoder_name;
+ agi::vfr::Framerate fps;
+ std::vector keyframes;
+ std::string warning;
+ std::string colorspace;
+
+ PClip RGB32Video;
+ VideoInfo vi;
+
+ AVSValue Open(agi::fs::path const& filename);
+
+public:
+ AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix);
+
+ std::shared_ptr GetFrame(int n);
+
+ 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; }
+};
+
+AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) {
agi::acs::CheckFileRead(filename);
std::lock_guard lock(avs.GetMutex());
@@ -273,4 +308,9 @@ std::shared_ptr AvisynthVideoProvider::GetFrame(int n) {
auto frame = RGB32Video->GetFrame(n, avs.GetEnv());
return std::make_shared(frame->GetReadPtr(), frame->GetRowSize() / 4, frame->GetHeight(), frame->GetPitch(), true);
}
+}
+
+std::unique_ptr CreateAvisynthVideoProvider(agi::fs::path const& path, std::string const& colormatrix) {
+ return agi::util::make_unique(path, colormatrix);
+}
#endif // HAVE_AVISYNTH
diff --git a/src/video_provider_avs.h b/src/video_provider_avs.h
deleted file mode 100644
index 93942e338..000000000
--- a/src/video_provider_avs.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2006, Fredrik Mellbin
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-/// @file video_provider_avs.h
-/// @see video_provider_avs.cpp
-/// @ingroup video_input
-///
-
-#ifdef WITH_AVISYNTH
-#include "include/aegisub/video_provider.h"
-
-#define VideoFrame AVSVideoFrame
-#include "avisynth.h"
-#undef VideoFrame
-#include "avisynth_wrap.h"
-
-class AvisynthVideoProvider: public VideoProvider {
- AviSynthWrapper avs;
- std::string decoder_name;
- agi::vfr::Framerate fps;
- std::vector keyframes;
- std::string warning;
- std::string colorspace;
-
- PClip RGB32Video;
- VideoInfo vi;
-
- AVSValue Open(agi::fs::path const& filename);
-
-public:
- AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix);
-
- std::shared_ptr GetFrame(int n);
-
- int GetFrameCount() const { return vi.num_frames; }
- agi::vfr::Framerate GetFPS() const { return fps; }
- int GetWidth() const { return vi.width; }
- int GetHeight() const { return vi.height; }
- double GetDAR() const { return 0; }
- std::vector GetKeyFrames() const { return keyframes; }
- std::string GetWarning() const { return warning; }
- std::string GetDecoderName() const { return decoder_name; }
- std::string GetColorSpace() const { return colorspace; }
-};
-#endif
diff --git a/src/video_provider_cache.cpp b/src/video_provider_cache.cpp
index a56e552fd..69a03dd7f 100644
--- a/src/video_provider_cache.cpp
+++ b/src/video_provider_cache.cpp
@@ -16,25 +16,16 @@
#include "config.h"
-#include "video_provider_cache.h"
+#include "include/aegisub/video_provider.h"
#include "options.h"
#include "video_frame.h"
-#include
-#include
+#include
-#if BOOST_VERSION <= 105200
-// Compilation fails without this with boost 1.52. I have no idea why.
-static bool operator==(VideoFrame const& a, VideoFrame const& b) {
- return a.width == b.width
- && a.height == b.height
- && a.pitch == b.pitch
- && a.flipped == b.flipped
- && a.data == b.data;
-}
-#endif
+#include
+namespace {
/// A video frame and its frame number
struct CachedFrame final : public VideoFrame {
int frame_number;
@@ -46,29 +37,47 @@ struct CachedFrame final : public VideoFrame {
}
};
-VideoProviderCache::VideoProviderCache(std::unique_ptr parent)
-: master(std::move(parent))
-, max_cache_size(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes
-{
-}
+/// @class VideoProviderCache
+/// @brief A wrapper around a video provider which provides LRU caching
+class VideoProviderCache final : public VideoProvider {
+ /// The source provider to get frames from
+ std::unique_ptr master;
-VideoProviderCache::~VideoProviderCache() {
-}
+ /// @brief Maximum size of the cache in bytes
+ ///
+ /// Note that this is a soft limit. The cache stops allocating new frames
+ /// once it has exceeded the limit, but it never tries to shrink
+ const size_t max_cache_size;
+
+ /// Cache of video frames with the most recently used ones at the front
+ std::list cache;
+
+public:
+ VideoProviderCache(std::unique_ptr master)
+ : master(std::move(master))
+ , max_cache_size(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes
+ {
+ }
+
+ std::shared_ptr GetFrame(int n) override;
+
+ int GetFrameCount() const override { return master->GetFrameCount(); }
+ int GetWidth() const override { return master->GetWidth(); }
+ int GetHeight() const override { return master->GetHeight(); }
+ double GetDAR() const override { return master->GetDAR(); }
+ agi::vfr::Framerate GetFPS() const override { return master->GetFPS(); }
+ std::vector GetKeyFrames() const override { return master->GetKeyFrames(); }
+ std::string GetWarning() const override { return master->GetWarning(); }
+ std::string GetDecoderName() const override { return master->GetDecoderName(); }
+ std::string GetColorSpace() const override { return master->GetColorSpace(); }
+};
std::shared_ptr VideoProviderCache::GetFrame(int n) {
size_t total_size = 0;
for (auto cur = cache.begin(); cur != cache.end(); ++cur) {
if (cur->frame_number == n) {
-#if BOOST_VERSION <= 105200
- // Until boost 1.52, boost::container::list incorrectly asserted
- // that this != &other, so do an extra splice through an empty list
- decltype(cache) temp;
- temp.splice(temp.begin(), cache, cur);
- cache.splice(cache.begin(), temp, temp.begin());
-#else
cache.splice(cache.begin(), cache, cur); // Move to front
-#endif
return std::make_shared(cache.front());
}
@@ -83,3 +92,8 @@ std::shared_ptr VideoProviderCache::GetFrame(int n) {
return frame;
}
+}
+
+std::unique_ptr CreateCacheVideoProvider(std::unique_ptr parent) {
+ return agi::util::make_unique(std::move(parent));
+}
diff --git a/src/video_provider_cache.h b/src/video_provider_cache.h
deleted file mode 100644
index 8fe033087..000000000
--- a/src/video_provider_cache.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2013, Thomas Goyne
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-#include
-
-#include "include/aegisub/video_provider.h"
-
-struct CachedFrame;
-
-/// @class VideoProviderCache
-/// @brief A wrapper around a video provider which provides LRU caching
-class VideoProviderCache final : public VideoProvider {
- /// The source provider to get frames from
- std::unique_ptr master;
-
- /// @brief Maximum size of the cache in bytes
- ///
- /// Note that this is a soft limit. The cache stops allocating new frames
- /// once it has exceeded the limit, but it never tries to shrink
- const size_t max_cache_size;
-
- /// Cache of video frames with the most recently used ones at the front
- boost::container::list cache;
-
-public:
- VideoProviderCache(std::unique_ptr master);
- ~VideoProviderCache();
-
- std::shared_ptr GetFrame(int n) override;
-
- int GetFrameCount() const override { return master->GetFrameCount(); }
- int GetWidth() const override { return master->GetWidth(); }
- int GetHeight() const override { return master->GetHeight(); }
- double GetDAR() const override { return master->GetDAR(); }
- agi::vfr::Framerate GetFPS() const override { return master->GetFPS(); }
- std::vector GetKeyFrames() const override { return master->GetKeyFrames(); }
- std::string GetWarning() const override { return master->GetWarning(); }
- std::string GetDecoderName() const override { return master->GetDecoderName(); }
- std::string GetColorSpace() const override { return master->GetColorSpace(); }
-};
diff --git a/src/video_provider_dummy.cpp b/src/video_provider_dummy.cpp
index 609242d35..3c70357ae 100644
--- a/src/video_provider_dummy.cpp
+++ b/src/video_provider_dummy.cpp
@@ -49,13 +49,18 @@
#include
#include
-void DummyVideoProvider::Create(double fps, int frames, int width, int height, unsigned char red, unsigned char green, unsigned char blue, bool pattern) {
- this->framecount = frames;
- this->fps = fps;
- this->width = width;
- this->height = height;
+DummyVideoProvider::DummyVideoProvider(double fps, int frames, int width, int height, agi::Color colour, bool pattern)
+: framecount(frames)
+, fps(fps)
+, width(width)
+, height(height)
+{
data.resize(width * height * 4);
+ auto red = colour.r;
+ auto green = colour.g;
+ auto blue = colour.b;
+
using namespace boost::gil;
auto dst = interleaved_view(width, height, (bgra8_pixel_t*)data.data(), 4 * width);
@@ -84,9 +89,17 @@ void DummyVideoProvider::Create(double fps, int frames, int width, int height, u
}
}
-DummyVideoProvider::DummyVideoProvider(agi::fs::path const& filename, std::string const&) {
+std::string DummyVideoProvider::MakeFilename(double fps, int frames, int width, int height, agi::Color colour, bool pattern) {
+ return str(boost::format("?dummy:%f:%d:%d:%d:%d:%d:%d:%s") % fps % frames % width % height % (int)colour.r % (int)colour.g % (int)colour.b % (pattern ? "c" : ""));
+}
+
+std::shared_ptr DummyVideoProvider::GetFrame(int) {
+ return std::make_shared(data.data(), width, height, width * 4, false);
+}
+
+std::unique_ptr CreateDummyVideoProvider(agi::fs::path const& filename, std::string const&) {
if (!boost::starts_with(filename.string(), "?dummy"))
- throw agi::fs::FileNotFound(std::string("Attempted creating dummy video provider with non-dummy filename"));
+ return {};
std::vector toks;
auto const& fields = filename.string().substr(7);
@@ -109,17 +122,5 @@ DummyVideoProvider::DummyVideoProvider(agi::fs::path const& filename, std::strin
bool pattern = toks[i] == "c";
- Create(fps, frames, width, height, red, green, blue, pattern);
-}
-
-DummyVideoProvider::DummyVideoProvider(double fps, int frames, int width, int height, agi::Color colour, bool pattern) {
- Create(fps, frames, width, height, colour.r, colour.g, colour.b, pattern);
-}
-
-std::string DummyVideoProvider::MakeFilename(double fps, int frames, int width, int height, agi::Color colour, bool pattern) {
- return str(boost::format("?dummy:%f:%d:%d:%d:%d:%d:%d:%s") % fps % frames % width % height % (int)colour.r % (int)colour.g % (int)colour.b % (pattern ? "c" : ""));
-}
-
-std::shared_ptr DummyVideoProvider::GetFrame(int) {
- return std::make_shared(data.data(), width, height, width * 4, false);
-}
+ return agi::util::make_unique(fps, frames, width, height, agi::Color(red, green, blue), pattern);
+}
\ No newline at end of file
diff --git a/src/video_provider_dummy.h b/src/video_provider_dummy.h
index 97d31e602..8826e6594 100644
--- a/src/video_provider_dummy.h
+++ b/src/video_provider_dummy.h
@@ -50,21 +50,7 @@ class DummyVideoProvider final : public VideoProvider {
/// The data for the image returned for all frames
std::vector data;
- /// Create the dummy frame from the given parameters
- /// @param fps Frame rate of the dummy video
- /// @param frames Length in frames of the dummy video
- /// @param width Width in pixels of the dummy video
- /// @param height Height in pixels of the dummy video
- /// @param red Red component of the primary colour of the dummy video
- /// @param green Green component of the primary colour of the dummy video
- /// @param blue Blue component of the primary colour of the dummy video
- /// @param pattern Use a checkerboard pattern rather than a solid colour
- void Create(double fps, int frames, int width, int height, unsigned char red, unsigned char green, unsigned char blue, bool pattern);
-
public:
- /// Create a dummy video from a string returned from MakeFilename
- DummyVideoProvider(agi::fs::path const& filename, std::string const& colormatix);
-
/// Create a dummy video from separate parameters
/// @param fps Frame rate of the dummy video
/// @param frames Length in frames of the dummy video
diff --git a/src/video_provider_ffmpegsource.cpp b/src/video_provider_ffmpegsource.cpp
index b0d359dc4..7a43ee348 100644
--- a/src/video_provider_ffmpegsource.cpp
+++ b/src/video_provider_ffmpegsource.cpp
@@ -35,7 +35,8 @@
#include "config.h"
#ifdef WITH_FFMS2
-#include "video_provider_ffmpegsource.h"
+#include "ffmpegsource_common.h"
+#include "include/aegisub/video_provider.h"
#include "compat.h"
#include "options.h"
@@ -44,11 +45,47 @@
#include "video_frame.h"
#include
+#include
#include
#include
namespace {
+/// @class FFmpegSourceVideoProvider
+/// @brief Implements video loading through the FFMS library.
+class FFmpegSourceVideoProvider final : public VideoProvider, FFmpegSourceProvider {
+ /// video source object
+ agi::scoped_holder VideoSource;
+ const FFMS_VideoProperties *VideoInfo = nullptr; ///< video properties
+
+ int Width = -1; ///< width in pixels
+ int Height = -1; ///< height in pixels
+ double DAR; ///< display aspect ratio
+ std::vector KeyFramesList; ///< list of keyframes
+ agi::vfr::Framerate Timecodes; ///< vfr object
+ std::string ColorSpace; ///< Colorspace name
+
+ char FFMSErrMsg[1024]; ///< FFMS error message
+ FFMS_ErrorInfo ErrInfo; ///< FFMS error codes/messages
+
+ void LoadVideo(agi::fs::path const& filename, std::string const& colormatrix);
+
+public:
+ FFmpegSourceVideoProvider(agi::fs::path const& filename, std::string const& colormatrix);
+
+ std::shared_ptr GetFrame(int n) override;
+
+ 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::vector GetKeyFrames() const override { return KeyFramesList; };
+ std::string GetDecoderName() const override { return "FFmpegSource"; }
+ bool WantsCaching() const override { return true; }
+};
+
std::string colormatrix_description(int cs, int cr) {
// Assuming TV for unspecified
std::string str = cr == FFMS_CR_JPEG ? "PC" : "TV";
@@ -70,7 +107,6 @@ std::string colormatrix_description(int cs, int cr) {
throw VideoOpenError("Unknown video color space");
}
}
-}
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) try
: VideoSource(nullptr, FFMS_DestroyVideoSource)
@@ -247,5 +283,10 @@ std::shared_ptr FFmpegSourceVideoProvider::GetFrame(int n) {
return std::make_shared(frame->Data[0], Width, Height, frame->Linesize[0], false);
}
+}
+
+std::unique_ptr CreateFFmpegSourceVideoProvider(agi::fs::path const& path, std::string const& colormatrix) {
+ return agi::util::make_unique(path, colormatrix);
+}
#endif /* WITH_FFMS2 */
diff --git a/src/video_provider_ffmpegsource.h b/src/video_provider_ffmpegsource.h
deleted file mode 100644
index 76139b473..000000000
--- a/src/video_provider_ffmpegsource.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2008-2009, Karl Blomster
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-/// @file video_provider_ffmpegsource.h
-/// @see video_provider_ffmpegsource.cpp
-/// @ingroup video_input ffms
-///
-
-#ifdef WITH_FFMS2
-#include "ffmpegsource_common.h"
-#include "include/aegisub/video_provider.h"
-
-/// @class FFmpegSourceVideoProvider
-/// @brief Implements video loading through the FFMS library.
-class FFmpegSourceVideoProvider final : public VideoProvider, FFmpegSourceProvider {
- /// video source object
- agi::scoped_holder VideoSource;
- const FFMS_VideoProperties *VideoInfo = nullptr; ///< video properties
-
- int Width = -1; ///< width in pixels
- int Height = -1; ///< height in pixels
- double DAR; ///< display aspect ratio
- std::vector KeyFramesList; ///< list of keyframes
- agi::vfr::Framerate Timecodes; ///< vfr object
- std::string ColorSpace; ///< Colorspace name
-
- char FFMSErrMsg[1024]; ///< FFMS error message
- FFMS_ErrorInfo ErrInfo; ///< FFMS error codes/messages
-
- void LoadVideo(agi::fs::path const& filename, std::string const& colormatrix);
-
-public:
- FFmpegSourceVideoProvider(agi::fs::path const& filename, std::string const& colormatrix);
-
- std::shared_ptr GetFrame(int n) override;
-
- 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::vector GetKeyFrames() const override { return KeyFramesList; };
- std::string GetDecoderName() const override { return "FFmpegSource"; }
- bool WantsCaching() const override { return true; }
-};
-#endif /* WITH_FFMS2 */
diff --git a/src/video_provider_manager.cpp b/src/video_provider_manager.cpp
index 116feac81..b74697350 100644
--- a/src/video_provider_manager.cpp
+++ b/src/video_provider_manager.cpp
@@ -1,68 +1,95 @@
-// Copyright (c) 2006, Rodrigo Braz Monteiro
-// All rights reserved.
+// Copyright (c) 2014, Thomas Goyne
//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/
-/// @file video_provider_manager.cpp
-/// @brief Keep track of installed video providers
-/// @ingroup video_input
-///
-
#include "config.h"
#include "video_provider_manager.h"
+#include "include/aegisub/video_provider.h"
#include "options.h"
-#include "video_provider_avs.h"
-#include "video_provider_cache.h"
-#include "video_provider_dummy.h"
-#include "video_provider_ffmpegsource.h"
-#include "video_provider_yuv4mpeg.h"
#include
#include
#include
-std::unique_ptr VideoProviderFactory::GetProvider(agi::fs::path const& video_file, std::string const& colormatrix) {
- std::vector factories = GetClasses(OPT_GET("Video/Provider")->GetString());
- factories.insert(factories.begin(), "YUV4MPEG");
- factories.insert(factories.begin(), "Dummy");
+std::unique_ptr CreateDummyVideoProvider(agi::fs::path const&, std::string const&);
+std::unique_ptr CreateYUV4MPEGVideoProvider(agi::fs::path const&, std::string const&);
+std::unique_ptr CreateFFmpegSourceVideoProvider(agi::fs::path const&, std::string const&);
+std::unique_ptr CreateAvisynthVideoProvider(agi::fs::path const&, std::string const&);
+
+std::unique_ptr CreateCacheVideoProvider(std::unique_ptr);
+
+namespace {
+ using factory_fn = std::unique_ptr (*)(agi::fs::path const&, std::string const&);
+ struct factory {
+ const char *name;
+ factory_fn create;
+ bool hidden;
+ };
+
+ const factory providers[] = {
+ {"Dummy", CreateDummyVideoProvider, true},
+ {"YUV4MPEG", CreateYUV4MPEGVideoProvider, true},
+#ifdef WITH_FFMS2
+ {"FFmpegSource", CreateFFmpegSourceVideoProvider, false},
+#endif
+#ifdef WITH_AVISYNTH
+ {"Avisynth", CreateAvisynthVideoProvider, false},
+#endif
+ };
+}
+
+std::vector VideoProviderFactory::GetClasses() {
+ std::vector list;
+ for (auto const& provider : providers) {
+ if (!provider.hidden)
+ list.push_back(provider.name);
+ }
+ return list;
+}
+
+std::unique_ptr VideoProviderFactory::GetProvider(agi::fs::path const& filename, std::string const& colormatrix) {
+ auto preferred = OPT_GET("Video/Provider")->GetString();
+ std::vector sorted;
+ auto preferred_insertion_point = sorted.end();
+ for (auto const& provider : providers) {
+ if (provider.hidden)
+ sorted.push_back(&provider);
+ else if (preferred_insertion_point == sorted.end()) {
+ sorted.push_back(&provider);
+ preferred_insertion_point = prev(sorted.end());
+ }
+ else if (preferred == provider.name)
+ sorted.insert(preferred_insertion_point, &provider);
+ else
+ sorted.push_back(&provider);
+ }
bool found = false;
bool supported = false;
std::string errors;
errors.reserve(1024);
- for (auto const& factory : factories) {
+ for (auto factory : sorted) {
std::string err;
try {
- auto provider = Create(factory, video_file, colormatrix);
- LOG_I("manager/video/provider") << factory << ": opened " << video_file;
- return provider->WantsCaching() ? agi::util::make_unique(std::move(provider)) : std::move(provider);
+ auto provider = factory->create(filename, colormatrix);
+ if (!provider) continue;
+ LOG_I("manager/video/provider") << factory->name << ": opened " << filename;
+ return provider->WantsCaching() ? CreateCacheVideoProvider(std::move(provider)) : std::move(provider);
}
catch (agi::fs::FileNotFound const&) {
err = "file not found.";
@@ -82,26 +109,15 @@ std::unique_ptr VideoProviderFactory::GetProvider(agi::fs::path c
err = ex.GetMessage();
}
- errors += factory + ": " + err + "\n";
- LOG_D("manager/video/provider") << factory << ": " << err;
+ errors += std::string(factory->name) + ": " + err + "\n";
+ LOG_D("manager/video/provider") << factory->name << ": " << err;
}
// No provider could open the file
- LOG_E("manager/video/provider") << "Could not open " << video_file;
- std::string msg = "Could not open " + video_file.string() + ":\n" + errors;
+ LOG_E("manager/video/provider") << "Could not open " << filename;
+ std::string msg = "Could not open " + filename.string() + ":\n" + errors;
- if (!found) throw agi::fs::FileNotFound(video_file.string());
+ if (!found) throw agi::fs::FileNotFound(filename.string());
if (!supported) throw VideoNotSupported(msg);
throw VideoOpenError(msg);
}
-
-void VideoProviderFactory::RegisterProviders() {
-#ifdef WITH_AVISYNTH
- Register("Avisynth");
-#endif
-#ifdef WITH_FFMS2
- Register("FFmpegSource");
-#endif
- Register("Dummy", true);
- Register("YUV4MPEG", true);
-}
diff --git a/src/video_provider_manager.h b/src/video_provider_manager.h
index 6632f75ef..718401e73 100644
--- a/src/video_provider_manager.h
+++ b/src/video_provider_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2013, Thomas Goyne
+// Copyright (c) 2014, Thomas Goyne
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -14,13 +14,15 @@
//
// Aegisub Project http://www.aegisub.org/
-#include "factory_manager.h"
-#include "include/aegisub/video_provider.h"
-
#include
-class VideoProviderFactory final : public Factory {
-public:
+#include
+#include
+#include
+
+class VideoProvider;
+
+struct VideoProviderFactory {
+ static std::vector GetClasses();
static std::unique_ptr GetProvider(agi::fs::path const& video_file, std::string const& colormatrix);
- static void RegisterProviders();
};
diff --git a/src/video_provider_yuv4mpeg.cpp b/src/video_provider_yuv4mpeg.cpp
index 527bf958f..3bed2812e 100644
--- a/src/video_provider_yuv4mpeg.cpp
+++ b/src/video_provider_yuv4mpeg.cpp
@@ -34,7 +34,7 @@
#include "config.h"
-#include "video_provider_yuv4mpeg.h"
+#include "include/aegisub/video_provider.h"
#include "compat.h"
#include "utils.h"
@@ -47,11 +47,122 @@
#include
#include
+#include
+#include
+
+/// the maximum allowed header length, in bytes
+#define YUV4MPEG_HEADER_MAXLEN 128
+
+namespace {
+
+/// @class YUV4MPEGVideoProvider
+/// @brief Implements reading of YUV4MPEG uncompressed video files
+class YUV4MPEGVideoProvider final : public VideoProvider {
+ /// Pixel formats
+ enum Y4M_PixelFormat {
+ Y4M_PIXFMT_NONE = -1, /// not set/unknown
+
+ /// 4:2:0 sampling variants.
+ /// afaict the only difference between these three
+ /// is the chroma sample location, and nobody cares about that.
+ Y4M_PIXFMT_420JPEG, /// 4:2:0, H/V centered, for JPEG/MPEG-1
+ Y4M_PIXFMT_420MPEG2, /// 4:2:0, H cosited, for MPEG-2
+ Y4M_PIXFMT_420PALDV, /// 4:2:0, alternating Cb/Cr, for PAL-DV
+
+ Y4M_PIXFMT_411, /// 4:1:1, H cosited
+ Y4M_PIXFMT_422, /// 4:2:2, H cosited
+ Y4M_PIXFMT_444, /// 4:4:4, i.e. no chroma subsampling
+ Y4M_PIXFMT_444ALPHA, /// 4:4:4 plus alpha channel
+
+ Y4M_PIXFMT_MONO /// luma only (grayscale)
+ };
+
+
+ /// Interlacing mode for an entire stream
+ enum Y4M_InterlacingMode {
+ Y4M_ILACE_NOTSET = -1, /// undefined
+ Y4M_ILACE_PROGRESSIVE, /// progressive (no interlacing)
+
+ Y4M_ILACE_TFF, /// interlaced, top field first
+ Y4M_ILACE_BFF, /// interlaced, bottom field first
+
+ Y4M_ILACE_MIXED, /// mixed interlaced/progressive, possibly with RFF flags
+ Y4M_ILACE_UNKNOWN /// unknown interlacing mode (not the same as undefined)
+ };
+
+
+ /// Frame information flags
+ enum Y4M_FrameFlags {
+ Y4M_FFLAG_NOTSET = -1, /// undefined
+ Y4M_FFLAG_NONE = 0x0000, /// no flags set
+
+ /// field order/repeat field flags
+ Y4M_FFLAG_R_TFF = 0x0001, /// top field first
+ Y4M_FFLAG_R_TFF_R = 0x0002, /// top field first, and repeat that field
+ Y4M_FFLAG_R_BFF = 0x0004, /// bottom field first
+ Y4M_FFLAG_R_BFF_R = 0x0008, /// bottom field first, and repeat that field
+ Y4M_FFLAG_R_P = 0x0010, /// progressive
+ Y4M_FFLAG_R_P_R = 0x0020, /// progressive, and repeat frame once
+ Y4M_FFLAG_R_P_RR = 0x0040, /// progressive, and repeat frame twice
+
+ /// temporal sampling flags
+ Y4M_FFLAG_T_P = 0x0080, /// progressive (fields sampled at the same time)
+ Y4M_FFLAG_T_I = 0x0100, /// interlaced (fields sampled at different times)
+
+ /// chroma subsampling flags
+ Y4M_FFLAG_C_P = 0x0200, /// progressive (whole frame subsampled)
+ Y4M_FFLAG_C_I = 0x0400, /// interlaced (fields subsampled independently)
+ Y4M_FFLAG_C_UNKNOWN = 0x0800 /// unknown (only allowed for non-4:2:0 sampling)
+ };
+
+ agi::read_file_mapping file;
+ bool inited = false; /// initialization state
+
+ int w = 0, h = 0; /// frame width/height
+ int num_frames = -1; /// length of file in frames
+ int frame_sz; /// size of each frame in bytes
+ int luma_sz; /// size of the luma plane of each frame, in bytes
+ int chroma_sz; /// size of one of the two chroma planes of each frame, in bytes
+
+ Y4M_PixelFormat pixfmt = Y4M_PIXFMT_NONE; /// colorspace/pixel format
+ Y4M_InterlacingMode imode = Y4M_ILACE_NOTSET; /// interlacing mode (for the entire stream)
+ struct {
+ int num = -1; /// numerator
+ int den = 1; /// denominator
+ } fps_rat; /// framerate
+
+ agi::vfr::Framerate fps;
+
+ /// a list of byte positions detailing where in the file
+ /// each frame header can be found
+ std::vector seek_table;
+
+ void CheckFileFormat();
+ void ParseFileHeader(const std::vector& tags);
+ Y4M_FrameFlags ParseFrameHeader(const std::vector& tags);
+ std::vector ReadHeader(uint64_t &startpos);
+ int IndexFile(uint64_t pos);
+
+public:
+ YUV4MPEGVideoProvider(agi::fs::path const& filename);
+
+ std::shared_ptr GetFrame(int n) override;
+
+ int GetFrameCount() const override { return num_frames; }
+ int GetWidth() const override { return w; }
+ int GetHeight() const override { return h; }
+ double GetDAR() const override { return 0; }
+ agi::vfr::Framerate GetFPS() const override { return fps; }
+ std::vector GetKeyFrames() const override { return {}; }
+ std::string GetColorSpace() const override { return "TV.601"; }
+ std::string GetDecoderName() const override { return "YU4MPEG"; }
+ bool WantsCaching() const override { return true; }
+};
/// @brief Constructor
/// @param filename The filename to open
-YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename, std::string const&)
-: file(agi::util::make_unique(filename))
+YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename)
+: file(filename)
{
CheckFileFormat();
@@ -89,15 +200,13 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename, std:
throw VideoOpenError("Unable to determine file length");
}
-YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() { }
-
/// @brief Checks if the file is an YUV4MPEG file or not
/// Note that it reports the error by throwing an exception,
/// not by returning a false value.
void YUV4MPEGVideoProvider::CheckFileFormat() {
- if (file->size() < 10)
+ if (file.size() < 10)
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (too small)");
- if (strncmp("YUV4MPEG2 ", file->read(0, 10), 10))
+ if (strncmp("YUV4MPEG2 ", file.read(0, 10), 10))
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (bad magic)");
}
@@ -106,11 +215,11 @@ void YUV4MPEGVideoProvider::CheckFileFormat() {
/// @return A list of parameters
std::vector YUV4MPEGVideoProvider::ReadHeader(uint64_t &pos) {
std::vector tags;
- if (pos >= file->size())
+ if (pos >= file.size())
return tags;
- auto len = std::min(YUV4MPEG_HEADER_MAXLEN, file->size() - pos);
- auto buff = file->read(pos, len);
+ auto len = std::min(YUV4MPEG_HEADER_MAXLEN, file.size() - pos);
+ auto buff = file.read(pos, len);
// read header until terminating newline (0x0A) is found
auto curtag = buff;
@@ -307,7 +416,7 @@ std::shared_ptr YUV4MPEGVideoProvider::GetFrame(int n) {
throw "YUV4MPEG video provider: GetFrame: Unsupported source colorspace";
}
- auto src_y = reinterpret_cast(file->read(seek_table[n], luma_sz + chroma_sz * 2));
+ auto src_y = reinterpret_cast(file.read(seek_table[n], luma_sz + chroma_sz * 2));
auto src_u = src_y + luma_sz;
auto src_v = src_u + chroma_sz;
std::vector data;
@@ -337,3 +446,8 @@ std::shared_ptr YUV4MPEGVideoProvider::GetFrame(int n) {
return std::make_shared(data.data(), w, h, w * 4, false);
}
+}
+
+std::unique_ptr CreateYUV4MPEGVideoProvider(agi::fs::path const& path, std::string const&) {
+ return agi::util::make_unique(path);
+}
diff --git a/src/video_provider_yuv4mpeg.h b/src/video_provider_yuv4mpeg.h
deleted file mode 100644
index ac57502cd..000000000
--- a/src/video_provider_yuv4mpeg.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2009, Karl Blomster
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-/// @file video_provider_yuv4mpeg.h
-/// @see video_provider_yuv4mpeg.cpp
-/// @ingroup video_input
-///
-
-#include "include/aegisub/video_provider.h"
-
-#include
-#include
-
-namespace agi { class read_file_mapping; }
-
-/// the maximum allowed header length, in bytes
-#define YUV4MPEG_HEADER_MAXLEN 128
-
-/// @class YUV4MPEGVideoProvider
-/// @brief Implements reading of YUV4MPEG uncompressed video files
-class YUV4MPEGVideoProvider final : public VideoProvider {
- /// Pixel formats
- enum Y4M_PixelFormat {
- Y4M_PIXFMT_NONE = -1, /// not set/unknown
-
- /// 4:2:0 sampling variants.
- /// afaict the only difference between these three
- /// is the chroma sample location, and nobody cares about that.
- Y4M_PIXFMT_420JPEG, /// 4:2:0, H/V centered, for JPEG/MPEG-1
- Y4M_PIXFMT_420MPEG2, /// 4:2:0, H cosited, for MPEG-2
- Y4M_PIXFMT_420PALDV, /// 4:2:0, alternating Cb/Cr, for PAL-DV
-
- Y4M_PIXFMT_411, /// 4:1:1, H cosited
- Y4M_PIXFMT_422, /// 4:2:2, H cosited
- Y4M_PIXFMT_444, /// 4:4:4, i.e. no chroma subsampling
- Y4M_PIXFMT_444ALPHA, /// 4:4:4 plus alpha channel
-
- Y4M_PIXFMT_MONO /// luma only (grayscale)
- };
-
-
- /// Interlacing mode for an entire stream
- enum Y4M_InterlacingMode {
- Y4M_ILACE_NOTSET = -1, /// undefined
- Y4M_ILACE_PROGRESSIVE, /// progressive (no interlacing)
-
- Y4M_ILACE_TFF, /// interlaced, top field first
- Y4M_ILACE_BFF, /// interlaced, bottom field first
-
- Y4M_ILACE_MIXED, /// mixed interlaced/progressive, possibly with RFF flags
- Y4M_ILACE_UNKNOWN /// unknown interlacing mode (not the same as undefined)
- };
-
-
- /// Frame information flags
- enum Y4M_FrameFlags {
- Y4M_FFLAG_NOTSET = -1, /// undefined
- Y4M_FFLAG_NONE = 0x0000, /// no flags set
-
- /// field order/repeat field flags
- Y4M_FFLAG_R_TFF = 0x0001, /// top field first
- Y4M_FFLAG_R_TFF_R = 0x0002, /// top field first, and repeat that field
- Y4M_FFLAG_R_BFF = 0x0004, /// bottom field first
- Y4M_FFLAG_R_BFF_R = 0x0008, /// bottom field first, and repeat that field
- Y4M_FFLAG_R_P = 0x0010, /// progressive
- Y4M_FFLAG_R_P_R = 0x0020, /// progressive, and repeat frame once
- Y4M_FFLAG_R_P_RR = 0x0040, /// progressive, and repeat frame twice
-
- /// temporal sampling flags
- Y4M_FFLAG_T_P = 0x0080, /// progressive (fields sampled at the same time)
- Y4M_FFLAG_T_I = 0x0100, /// interlaced (fields sampled at different times)
-
- /// chroma subsampling flags
- Y4M_FFLAG_C_P = 0x0200, /// progressive (whole frame subsampled)
- Y4M_FFLAG_C_I = 0x0400, /// interlaced (fields subsampled independently)
- Y4M_FFLAG_C_UNKNOWN = 0x0800 /// unknown (only allowed for non-4:2:0 sampling)
- };
-
- std::unique_ptr file;
- bool inited = false; /// initialization state
-
- int w = 0, h = 0; /// frame width/height
- int num_frames = -1; /// length of file in frames
- int frame_sz; /// size of each frame in bytes
- int luma_sz; /// size of the luma plane of each frame, in bytes
- int chroma_sz; /// size of one of the two chroma planes of each frame, in bytes
-
- Y4M_PixelFormat pixfmt = Y4M_PIXFMT_NONE; /// colorspace/pixel format
- Y4M_InterlacingMode imode = Y4M_ILACE_NOTSET; /// interlacing mode (for the entire stream)
- struct {
- int num = -1; /// numerator
- int den = 1; /// denominator
- } fps_rat; /// framerate
-
- agi::vfr::Framerate fps;
-
- /// a list of byte positions detailing where in the file
- /// each frame header can be found
- std::vector seek_table;
-
- void CheckFileFormat();
- void ParseFileHeader(const std::vector& tags);
- Y4M_FrameFlags ParseFrameHeader(const std::vector& tags);
- std::vector ReadHeader(uint64_t &startpos);
- int IndexFile(uint64_t pos);
-
-public:
- YUV4MPEGVideoProvider(agi::fs::path const& filename, std::string const&);
- ~YUV4MPEGVideoProvider();
-
- std::shared_ptr GetFrame(int n) override;
-
- int GetFrameCount() const override { return num_frames; }
- int GetWidth() const override { return w; }
- int GetHeight() const override { return h; }
- double GetDAR() const override { return 0; }
- agi::vfr::Framerate GetFPS() const override { return fps; }
- std::vector GetKeyFrames() const override { return {}; }
- std::string GetColorSpace() const override { return "TV.601"; }
- std::string GetDecoderName() const override { return "YU4MPEG"; }
- bool WantsCaching() const override { return true; }
-};