forked from mia/Aegisub
Convert VideoProviderManager to AudioProviderManager's new design
This commit is contained in:
parent
36a71be19f
commit
470f85d365
18 changed files with 361 additions and 509 deletions
|
@ -243,12 +243,8 @@
|
||||||
<ClInclude Include="$(SrcDir)video_display.h" />
|
<ClInclude Include="$(SrcDir)video_display.h" />
|
||||||
<ClInclude Include="$(SrcDir)video_frame.h" />
|
<ClInclude Include="$(SrcDir)video_frame.h" />
|
||||||
<ClInclude Include="$(SrcDir)video_out_gl.h" />
|
<ClInclude Include="$(SrcDir)video_out_gl.h" />
|
||||||
<ClInclude Include="$(SrcDir)video_provider_avs.h" />
|
|
||||||
<ClInclude Include="$(SrcDir)video_provider_cache.h" />
|
|
||||||
<ClInclude Include="$(SrcDir)video_provider_dummy.h" />
|
<ClInclude Include="$(SrcDir)video_provider_dummy.h" />
|
||||||
<ClInclude Include="$(SrcDir)video_provider_ffmpegsource.h" />
|
|
||||||
<ClInclude Include="$(SrcDir)video_provider_manager.h" />
|
<ClInclude Include="$(SrcDir)video_provider_manager.h" />
|
||||||
<ClInclude Include="$(SrcDir)video_provider_yuv4mpeg.h" />
|
|
||||||
<ClInclude Include="$(SrcDir)video_slider.h" />
|
<ClInclude Include="$(SrcDir)video_slider.h" />
|
||||||
<ClInclude Include="$(SrcDir)visual_feature.h" />
|
<ClInclude Include="$(SrcDir)visual_feature.h" />
|
||||||
<ClInclude Include="$(SrcDir)visual_tool.h" />
|
<ClInclude Include="$(SrcDir)visual_tool.h" />
|
||||||
|
|
|
@ -390,21 +390,9 @@
|
||||||
<ClInclude Include="$(SrcDir)video_out_gl.h">
|
<ClInclude Include="$(SrcDir)video_out_gl.h">
|
||||||
<Filter>Video\UI</Filter>
|
<Filter>Video\UI</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="$(SrcDir)video_provider_avs.h">
|
|
||||||
<Filter>Video\Providers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)video_provider_yuv4mpeg.h">
|
|
||||||
<Filter>Video\Providers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)video_provider_cache.h">
|
|
||||||
<Filter>Video\Providers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)video_provider_dummy.h">
|
<ClInclude Include="$(SrcDir)video_provider_dummy.h">
|
||||||
<Filter>Video\Providers</Filter>
|
<Filter>Video\Providers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="$(SrcDir)video_provider_ffmpegsource.h">
|
|
||||||
<Filter>Video\Providers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)video_provider_manager.h">
|
<ClInclude Include="$(SrcDir)video_provider_manager.h">
|
||||||
<Filter>Video\Providers</Filter>
|
<Filter>Video\Providers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
#include "ass_time.h"
|
#include "ass_time.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "include/aegisub/context.h"
|
#include "include/aegisub/context.h"
|
||||||
|
#include "include/aegisub/video_provider.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
#include "video_provider_manager.h"
|
|
||||||
|
|
||||||
#include <boost/rational.hpp>
|
#include <boost/rational.hpp>
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "include/aegisub/menu.h"
|
#include "include/aegisub/menu.h"
|
||||||
#include "include/aegisub/toolbar.h"
|
#include "include/aegisub/toolbar.h"
|
||||||
#include "include/aegisub/hotkey.h"
|
#include "include/aegisub/hotkey.h"
|
||||||
|
#include "include/aegisub/video_provider.h"
|
||||||
|
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "audio_controller.h"
|
#include "audio_controller.h"
|
||||||
|
@ -69,7 +70,6 @@
|
||||||
#include "video_box.h"
|
#include "video_box.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
#include "video_provider_manager.h"
|
|
||||||
#include "video_slider.h"
|
#include "video_slider.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
|
@ -38,13 +38,11 @@
|
||||||
#include "include/aegisub/spellchecker.h"
|
#include "include/aegisub/spellchecker.h"
|
||||||
#include "include/aegisub/subtitles_provider.h"
|
#include "include/aegisub/subtitles_provider.h"
|
||||||
#include "plugin_manager.h"
|
#include "plugin_manager.h"
|
||||||
#include "video_provider_manager.h"
|
|
||||||
#include "auto4_lua_factory.h"
|
#include "auto4_lua_factory.h"
|
||||||
|
|
||||||
#include <libaegisub/util.h>
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
void RegisterBuiltInPlugins() {
|
void RegisterBuiltInPlugins() {
|
||||||
VideoProviderFactory::RegisterProviders();
|
|
||||||
AudioPlayerFactory::RegisterProviders();
|
AudioPlayerFactory::RegisterProviders();
|
||||||
SubtitlesProviderFactory::RegisterProviders();
|
SubtitlesProviderFactory::RegisterProviders();
|
||||||
SpellCheckerFactory::RegisterProviders();
|
SpellCheckerFactory::RegisterProviders();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "export_fixstyle.h"
|
#include "export_fixstyle.h"
|
||||||
#include "include/aegisub/subtitles_provider.h"
|
#include "include/aegisub/subtitles_provider.h"
|
||||||
|
#include "include/aegisub/video_provider.h"
|
||||||
#include "video_frame.h"
|
#include "video_frame.h"
|
||||||
#include "video_provider_manager.h"
|
#include "video_provider_manager.h"
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef WITH_AVISYNTH
|
#ifdef WITH_AVISYNTH
|
||||||
#include "video_provider_avs.h"
|
#include "include/aegisub/video_provider.h"
|
||||||
|
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "video_frame.h"
|
#include "video_frame.h"
|
||||||
|
@ -45,6 +45,7 @@
|
||||||
#include <libaegisub/fs.h>
|
#include <libaegisub/fs.h>
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/path.h>
|
#include <libaegisub/path.h>
|
||||||
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -53,8 +54,42 @@
|
||||||
#include <vfw.h>
|
#include <vfw.h>
|
||||||
#endif
|
#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<int> 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<VideoFrame> 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<int> 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);
|
agi::acs::CheckFileRead(filename);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(avs.GetMutex());
|
std::lock_guard<std::mutex> lock(avs.GetMutex());
|
||||||
|
@ -273,4 +308,9 @@ std::shared_ptr<VideoFrame> AvisynthVideoProvider::GetFrame(int n) {
|
||||||
auto frame = RGB32Video->GetFrame(n, avs.GetEnv());
|
auto frame = RGB32Video->GetFrame(n, avs.GetEnv());
|
||||||
return std::make_shared<VideoFrame>(frame->GetReadPtr(), frame->GetRowSize() / 4, frame->GetHeight(), frame->GetPitch(), true);
|
return std::make_shared<VideoFrame>(frame->GetReadPtr(), frame->GetRowSize() / 4, frame->GetHeight(), frame->GetPitch(), true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoProvider> CreateAvisynthVideoProvider(agi::fs::path const& path, std::string const& colormatrix) {
|
||||||
|
return agi::util::make_unique<AvisynthVideoProvider>(path, colormatrix);
|
||||||
|
}
|
||||||
#endif // HAVE_AVISYNTH
|
#endif // HAVE_AVISYNTH
|
||||||
|
|
|
@ -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<int> 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<VideoFrame> 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<int> GetKeyFrames() const { return keyframes; }
|
|
||||||
std::string GetWarning() const { return warning; }
|
|
||||||
std::string GetDecoderName() const { return decoder_name; }
|
|
||||||
std::string GetColorSpace() const { return colorspace; }
|
|
||||||
};
|
|
||||||
#endif
|
|
|
@ -16,25 +16,16 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "video_provider_cache.h"
|
#include "include/aegisub/video_provider.h"
|
||||||
|
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "video_frame.h"
|
#include "video_frame.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <libaegisub/util.h>
|
||||||
#include <boost/version.hpp>
|
|
||||||
|
|
||||||
#if BOOST_VERSION <= 105200
|
#include <list>
|
||||||
// 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
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
/// A video frame and its frame number
|
/// A video frame and its frame number
|
||||||
struct CachedFrame final : public VideoFrame {
|
struct CachedFrame final : public VideoFrame {
|
||||||
int frame_number;
|
int frame_number;
|
||||||
|
@ -46,29 +37,47 @@ struct CachedFrame final : public VideoFrame {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
VideoProviderCache::VideoProviderCache(std::unique_ptr<VideoProvider> parent)
|
/// @class VideoProviderCache
|
||||||
: master(std::move(parent))
|
/// @brief A wrapper around a video provider which provides LRU caching
|
||||||
, max_cache_size(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes
|
class VideoProviderCache final : public VideoProvider {
|
||||||
{
|
/// The source provider to get frames from
|
||||||
}
|
std::unique_ptr<VideoProvider> 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<CachedFrame> cache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VideoProviderCache(std::unique_ptr<VideoProvider> master)
|
||||||
|
: master(std::move(master))
|
||||||
|
, max_cache_size(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<VideoFrame> 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<int> 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<VideoFrame> VideoProviderCache::GetFrame(int n) {
|
std::shared_ptr<VideoFrame> VideoProviderCache::GetFrame(int n) {
|
||||||
size_t total_size = 0;
|
size_t total_size = 0;
|
||||||
|
|
||||||
for (auto cur = cache.begin(); cur != cache.end(); ++cur) {
|
for (auto cur = cache.begin(); cur != cache.end(); ++cur) {
|
||||||
if (cur->frame_number == n) {
|
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
|
cache.splice(cache.begin(), cache, cur); // Move to front
|
||||||
#endif
|
|
||||||
return std::make_shared<VideoFrame>(cache.front());
|
return std::make_shared<VideoFrame>(cache.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,3 +92,8 @@ std::shared_ptr<VideoFrame> VideoProviderCache::GetFrame(int n) {
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoProvider> CreateCacheVideoProvider(std::unique_ptr<VideoProvider> parent) {
|
||||||
|
return agi::util::make_unique<VideoProviderCache>(std::move(parent));
|
||||||
|
}
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
|
||||||
//
|
|
||||||
// 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 <boost/container/list.hpp>
|
|
||||||
|
|
||||||
#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<VideoProvider> 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<CachedFrame> cache;
|
|
||||||
|
|
||||||
public:
|
|
||||||
VideoProviderCache(std::unique_ptr<VideoProvider> master);
|
|
||||||
~VideoProviderCache();
|
|
||||||
|
|
||||||
std::shared_ptr<VideoFrame> 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<int> 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(); }
|
|
||||||
};
|
|
|
@ -49,13 +49,18 @@
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/gil/gil_all.hpp>
|
#include <boost/gil/gil_all.hpp>
|
||||||
|
|
||||||
void DummyVideoProvider::Create(double fps, int frames, int width, int height, unsigned char red, unsigned char green, unsigned char blue, bool pattern) {
|
DummyVideoProvider::DummyVideoProvider(double fps, int frames, int width, int height, agi::Color colour, bool pattern)
|
||||||
this->framecount = frames;
|
: framecount(frames)
|
||||||
this->fps = fps;
|
, fps(fps)
|
||||||
this->width = width;
|
, width(width)
|
||||||
this->height = height;
|
, height(height)
|
||||||
|
{
|
||||||
data.resize(width * height * 4);
|
data.resize(width * height * 4);
|
||||||
|
|
||||||
|
auto red = colour.r;
|
||||||
|
auto green = colour.g;
|
||||||
|
auto blue = colour.b;
|
||||||
|
|
||||||
using namespace boost::gil;
|
using namespace boost::gil;
|
||||||
auto dst = interleaved_view(width, height, (bgra8_pixel_t*)data.data(), 4 * width);
|
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<VideoFrame> DummyVideoProvider::GetFrame(int) {
|
||||||
|
return std::make_shared<VideoFrame>(data.data(), width, height, width * 4, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoProvider> CreateDummyVideoProvider(agi::fs::path const& filename, std::string const&) {
|
||||||
if (!boost::starts_with(filename.string(), "?dummy"))
|
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<std::string> toks;
|
std::vector<std::string> toks;
|
||||||
auto const& fields = filename.string().substr(7);
|
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";
|
bool pattern = toks[i] == "c";
|
||||||
|
|
||||||
Create(fps, frames, width, height, red, green, blue, pattern);
|
return agi::util::make_unique<DummyVideoProvider>(fps, frames, width, height, agi::Color(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<VideoFrame> DummyVideoProvider::GetFrame(int) {
|
|
||||||
return std::make_shared<VideoFrame>(data.data(), width, height, width * 4, false);
|
|
||||||
}
|
}
|
|
@ -50,21 +50,7 @@ class DummyVideoProvider final : public VideoProvider {
|
||||||
/// The data for the image returned for all frames
|
/// The data for the image returned for all frames
|
||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> 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:
|
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
|
/// Create a dummy video from separate parameters
|
||||||
/// @param fps Frame rate of the dummy video
|
/// @param fps Frame rate of the dummy video
|
||||||
/// @param frames Length in frames of the dummy video
|
/// @param frames Length in frames of the dummy video
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef WITH_FFMS2
|
#ifdef WITH_FFMS2
|
||||||
#include "video_provider_ffmpegsource.h"
|
#include "ffmpegsource_common.h"
|
||||||
|
#include "include/aegisub/video_provider.h"
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
@ -44,11 +45,47 @@
|
||||||
#include "video_frame.h"
|
#include "video_frame.h"
|
||||||
|
|
||||||
#include <libaegisub/fs.h>
|
#include <libaegisub/fs.h>
|
||||||
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
#include <wx/choicdlg.h>
|
#include <wx/choicdlg.h>
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
/// @class FFmpegSourceVideoProvider
|
||||||
|
/// @brief Implements video loading through the FFMS library.
|
||||||
|
class FFmpegSourceVideoProvider final : public VideoProvider, FFmpegSourceProvider {
|
||||||
|
/// video source object
|
||||||
|
agi::scoped_holder<FFMS_VideoSource*, void (FFMS_CC*)(FFMS_VideoSource*)> 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<int> 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<VideoFrame> 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<int> 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) {
|
std::string colormatrix_description(int cs, int cr) {
|
||||||
// Assuming TV for unspecified
|
// Assuming TV for unspecified
|
||||||
std::string str = cr == FFMS_CR_JPEG ? "PC" : "TV";
|
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");
|
throw VideoOpenError("Unknown video color space");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) try
|
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) try
|
||||||
: VideoSource(nullptr, FFMS_DestroyVideoSource)
|
: VideoSource(nullptr, FFMS_DestroyVideoSource)
|
||||||
|
@ -247,5 +283,10 @@ std::shared_ptr<VideoFrame> FFmpegSourceVideoProvider::GetFrame(int n) {
|
||||||
|
|
||||||
return std::make_shared<VideoFrame>(frame->Data[0], Width, Height, frame->Linesize[0], false);
|
return std::make_shared<VideoFrame>(frame->Data[0], Width, Height, frame->Linesize[0], false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoProvider> CreateFFmpegSourceVideoProvider(agi::fs::path const& path, std::string const& colormatrix) {
|
||||||
|
return agi::util::make_unique<FFmpegSourceVideoProvider>(path, colormatrix);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* WITH_FFMS2 */
|
#endif /* WITH_FFMS2 */
|
||||||
|
|
|
@ -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<FFMS_VideoSource*, void (FFMS_CC*)(FFMS_VideoSource*)> 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<int> 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<VideoFrame> 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<int> GetKeyFrames() const override { return KeyFramesList; };
|
|
||||||
std::string GetDecoderName() const override { return "FFmpegSource"; }
|
|
||||||
bool WantsCaching() const override { return true; }
|
|
||||||
};
|
|
||||||
#endif /* WITH_FFMS2 */
|
|
|
@ -1,68 +1,95 @@
|
||||||
// Copyright (c) 2006, Rodrigo Braz Monteiro
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
// All rights reserved.
|
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// 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,
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// this list of conditions and the following disclaimer.
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
// and/or other materials provided with the distribution.
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// may be used to endorse or promote products derived from this software
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 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/
|
// 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 "config.h"
|
||||||
|
|
||||||
#include "video_provider_manager.h"
|
#include "video_provider_manager.h"
|
||||||
|
|
||||||
|
#include "include/aegisub/video_provider.h"
|
||||||
#include "options.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 <libaegisub/fs.h>
|
#include <libaegisub/fs.h>
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/util.h>
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
std::unique_ptr<VideoProvider> VideoProviderFactory::GetProvider(agi::fs::path const& video_file, std::string const& colormatrix) {
|
std::unique_ptr<VideoProvider> CreateDummyVideoProvider(agi::fs::path const&, std::string const&);
|
||||||
std::vector<std::string> factories = GetClasses(OPT_GET("Video/Provider")->GetString());
|
std::unique_ptr<VideoProvider> CreateYUV4MPEGVideoProvider(agi::fs::path const&, std::string const&);
|
||||||
factories.insert(factories.begin(), "YUV4MPEG");
|
std::unique_ptr<VideoProvider> CreateFFmpegSourceVideoProvider(agi::fs::path const&, std::string const&);
|
||||||
factories.insert(factories.begin(), "Dummy");
|
std::unique_ptr<VideoProvider> CreateAvisynthVideoProvider(agi::fs::path const&, std::string const&);
|
||||||
|
|
||||||
|
std::unique_ptr<VideoProvider> CreateCacheVideoProvider(std::unique_ptr<VideoProvider>);
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using factory_fn = std::unique_ptr<VideoProvider> (*)(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<std::string> VideoProviderFactory::GetClasses() {
|
||||||
|
std::vector<std::string> list;
|
||||||
|
for (auto const& provider : providers) {
|
||||||
|
if (!provider.hidden)
|
||||||
|
list.push_back(provider.name);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoProvider> VideoProviderFactory::GetProvider(agi::fs::path const& filename, std::string const& colormatrix) {
|
||||||
|
auto preferred = OPT_GET("Video/Provider")->GetString();
|
||||||
|
std::vector<const factory *> 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 found = false;
|
||||||
bool supported = false;
|
bool supported = false;
|
||||||
std::string errors;
|
std::string errors;
|
||||||
errors.reserve(1024);
|
errors.reserve(1024);
|
||||||
|
|
||||||
for (auto const& factory : factories) {
|
for (auto factory : sorted) {
|
||||||
std::string err;
|
std::string err;
|
||||||
try {
|
try {
|
||||||
auto provider = Create(factory, video_file, colormatrix);
|
auto provider = factory->create(filename, colormatrix);
|
||||||
LOG_I("manager/video/provider") << factory << ": opened " << video_file;
|
if (!provider) continue;
|
||||||
return provider->WantsCaching() ? agi::util::make_unique<VideoProviderCache>(std::move(provider)) : std::move(provider);
|
LOG_I("manager/video/provider") << factory->name << ": opened " << filename;
|
||||||
|
return provider->WantsCaching() ? CreateCacheVideoProvider(std::move(provider)) : std::move(provider);
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileNotFound const&) {
|
catch (agi::fs::FileNotFound const&) {
|
||||||
err = "file not found.";
|
err = "file not found.";
|
||||||
|
@ -82,26 +109,15 @@ std::unique_ptr<VideoProvider> VideoProviderFactory::GetProvider(agi::fs::path c
|
||||||
err = ex.GetMessage();
|
err = ex.GetMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
errors += factory + ": " + err + "\n";
|
errors += std::string(factory->name) + ": " + err + "\n";
|
||||||
LOG_D("manager/video/provider") << factory << ": " << err;
|
LOG_D("manager/video/provider") << factory->name << ": " << err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No provider could open the file
|
// No provider could open the file
|
||||||
LOG_E("manager/video/provider") << "Could not open " << video_file;
|
LOG_E("manager/video/provider") << "Could not open " << filename;
|
||||||
std::string msg = "Could not open " + video_file.string() + ":\n" + errors;
|
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);
|
if (!supported) throw VideoNotSupported(msg);
|
||||||
throw VideoOpenError(msg);
|
throw VideoOpenError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoProviderFactory::RegisterProviders() {
|
|
||||||
#ifdef WITH_AVISYNTH
|
|
||||||
Register<AvisynthVideoProvider>("Avisynth");
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_FFMS2
|
|
||||||
Register<FFmpegSourceVideoProvider>("FFmpegSource");
|
|
||||||
#endif
|
|
||||||
Register<DummyVideoProvider>("Dummy", true);
|
|
||||||
Register<YUV4MPEGVideoProvider>("YUV4MPEG", true);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -14,13 +14,15 @@
|
||||||
//
|
//
|
||||||
// Aegisub Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
#include "factory_manager.h"
|
|
||||||
#include "include/aegisub/video_provider.h"
|
|
||||||
|
|
||||||
#include <libaegisub/fs_fwd.h>
|
#include <libaegisub/fs_fwd.h>
|
||||||
|
|
||||||
class VideoProviderFactory final : public Factory<VideoProvider, agi::fs::path, std::string> {
|
#include <memory>
|
||||||
public:
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class VideoProvider;
|
||||||
|
|
||||||
|
struct VideoProviderFactory {
|
||||||
|
static std::vector<std::string> GetClasses();
|
||||||
static std::unique_ptr<VideoProvider> GetProvider(agi::fs::path const& video_file, std::string const& colormatrix);
|
static std::unique_ptr<VideoProvider> GetProvider(agi::fs::path const& video_file, std::string const& colormatrix);
|
||||||
static void RegisterProviders();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "video_provider_yuv4mpeg.h"
|
#include "include/aegisub/video_provider.h"
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -47,11 +47,122 @@
|
||||||
|
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/// 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<uint64_t> seek_table;
|
||||||
|
|
||||||
|
void CheckFileFormat();
|
||||||
|
void ParseFileHeader(const std::vector<std::string>& tags);
|
||||||
|
Y4M_FrameFlags ParseFrameHeader(const std::vector<std::string>& tags);
|
||||||
|
std::vector<std::string> ReadHeader(uint64_t &startpos);
|
||||||
|
int IndexFile(uint64_t pos);
|
||||||
|
|
||||||
|
public:
|
||||||
|
YUV4MPEGVideoProvider(agi::fs::path const& filename);
|
||||||
|
|
||||||
|
std::shared_ptr<VideoFrame> 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<int> 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
|
/// @brief Constructor
|
||||||
/// @param filename The filename to open
|
/// @param filename The filename to open
|
||||||
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename, std::string const&)
|
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename)
|
||||||
: file(agi::util::make_unique<agi::read_file_mapping>(filename))
|
: file(filename)
|
||||||
{
|
{
|
||||||
CheckFileFormat();
|
CheckFileFormat();
|
||||||
|
|
||||||
|
@ -89,15 +200,13 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename, std:
|
||||||
throw VideoOpenError("Unable to determine file length");
|
throw VideoOpenError("Unable to determine file length");
|
||||||
}
|
}
|
||||||
|
|
||||||
YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() { }
|
|
||||||
|
|
||||||
/// @brief Checks if the file is an YUV4MPEG file or not
|
/// @brief Checks if the file is an YUV4MPEG file or not
|
||||||
/// Note that it reports the error by throwing an exception,
|
/// Note that it reports the error by throwing an exception,
|
||||||
/// not by returning a false value.
|
/// not by returning a false value.
|
||||||
void YUV4MPEGVideoProvider::CheckFileFormat() {
|
void YUV4MPEGVideoProvider::CheckFileFormat() {
|
||||||
if (file->size() < 10)
|
if (file.size() < 10)
|
||||||
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (too small)");
|
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)");
|
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (bad magic)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,11 +215,11 @@ void YUV4MPEGVideoProvider::CheckFileFormat() {
|
||||||
/// @return A list of parameters
|
/// @return A list of parameters
|
||||||
std::vector<std::string> YUV4MPEGVideoProvider::ReadHeader(uint64_t &pos) {
|
std::vector<std::string> YUV4MPEGVideoProvider::ReadHeader(uint64_t &pos) {
|
||||||
std::vector<std::string> tags;
|
std::vector<std::string> tags;
|
||||||
if (pos >= file->size())
|
if (pos >= file.size())
|
||||||
return tags;
|
return tags;
|
||||||
|
|
||||||
auto len = std::min<uint64_t>(YUV4MPEG_HEADER_MAXLEN, file->size() - pos);
|
auto len = std::min<uint64_t>(YUV4MPEG_HEADER_MAXLEN, file.size() - pos);
|
||||||
auto buff = file->read(pos, len);
|
auto buff = file.read(pos, len);
|
||||||
|
|
||||||
// read header until terminating newline (0x0A) is found
|
// read header until terminating newline (0x0A) is found
|
||||||
auto curtag = buff;
|
auto curtag = buff;
|
||||||
|
@ -307,7 +416,7 @@ std::shared_ptr<VideoFrame> YUV4MPEGVideoProvider::GetFrame(int n) {
|
||||||
throw "YUV4MPEG video provider: GetFrame: Unsupported source colorspace";
|
throw "YUV4MPEG video provider: GetFrame: Unsupported source colorspace";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto src_y = reinterpret_cast<const unsigned char *>(file->read(seek_table[n], luma_sz + chroma_sz * 2));
|
auto src_y = reinterpret_cast<const unsigned char *>(file.read(seek_table[n], luma_sz + chroma_sz * 2));
|
||||||
auto src_u = src_y + luma_sz;
|
auto src_u = src_y + luma_sz;
|
||||||
auto src_v = src_u + chroma_sz;
|
auto src_v = src_u + chroma_sz;
|
||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
|
@ -337,3 +446,8 @@ std::shared_ptr<VideoFrame> YUV4MPEGVideoProvider::GetFrame(int n) {
|
||||||
|
|
||||||
return std::make_shared<VideoFrame>(data.data(), w, h, w * 4, false);
|
return std::make_shared<VideoFrame>(data.data(), w, h, w * 4, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoProvider> CreateYUV4MPEGVideoProvider(agi::fs::path const& path, std::string const&) {
|
||||||
|
return agi::util::make_unique<YUV4MPEGVideoProvider>(path);
|
||||||
|
}
|
||||||
|
|
|
@ -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 <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
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<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<uint64_t> seek_table;
|
|
||||||
|
|
||||||
void CheckFileFormat();
|
|
||||||
void ParseFileHeader(const std::vector<std::string>& tags);
|
|
||||||
Y4M_FrameFlags ParseFrameHeader(const std::vector<std::string>& tags);
|
|
||||||
std::vector<std::string> ReadHeader(uint64_t &startpos);
|
|
||||||
int IndexFile(uint64_t pos);
|
|
||||||
|
|
||||||
public:
|
|
||||||
YUV4MPEGVideoProvider(agi::fs::path const& filename, std::string const&);
|
|
||||||
~YUV4MPEGVideoProvider();
|
|
||||||
|
|
||||||
std::shared_ptr<VideoFrame> 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<int> 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; }
|
|
||||||
};
|
|
Loading…
Reference in a new issue