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_frame.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_ffmpegsource.h" />
|
||||
<ClInclude Include="$(SrcDir)video_provider_manager.h" />
|
||||
<ClInclude Include="$(SrcDir)video_provider_yuv4mpeg.h" />
|
||||
<ClInclude Include="$(SrcDir)video_slider.h" />
|
||||
<ClInclude Include="$(SrcDir)visual_feature.h" />
|
||||
<ClInclude Include="$(SrcDir)visual_tool.h" />
|
||||
|
|
|
@ -390,21 +390,9 @@
|
|||
<ClInclude Include="$(SrcDir)video_out_gl.h">
|
||||
<Filter>Video\UI</Filter>
|
||||
</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">
|
||||
<Filter>Video\Providers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)video_provider_ffmpegsource.h">
|
||||
<Filter>Video\Providers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)video_provider_manager.h">
|
||||
<Filter>Video\Providers</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -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 <boost/rational.hpp>
|
||||
|
||||
|
|
|
@ -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 <boost/algorithm/string/predicate.hpp>
|
||||
|
|
|
@ -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 <libaegisub/util.h>
|
||||
|
||||
void RegisterBuiltInPlugins() {
|
||||
VideoProviderFactory::RegisterProviders();
|
||||
AudioPlayerFactory::RegisterProviders();
|
||||
SubtitlesProviderFactory::RegisterProviders();
|
||||
SpellCheckerFactory::RegisterProviders();
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 <libaegisub/fs.h>
|
||||
#include <libaegisub/log.h>
|
||||
#include <libaegisub/path.h>
|
||||
#include <libaegisub/util.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <mutex>
|
||||
|
@ -53,8 +54,42 @@
|
|||
#include <vfw.h>
|
||||
#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);
|
||||
|
||||
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());
|
||||
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
|
||||
|
|
|
@ -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 "video_provider_cache.h"
|
||||
#include "include/aegisub/video_provider.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "video_frame.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/version.hpp>
|
||||
#include <libaegisub/util.h>
|
||||
|
||||
#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 <list>
|
||||
|
||||
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<VideoProvider> 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<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) {
|
||||
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<VideoFrame>(cache.front());
|
||||
}
|
||||
|
||||
|
@ -83,3 +92,8 @@ std::shared_ptr<VideoFrame> VideoProviderCache::GetFrame(int n) {
|
|||
|
||||
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/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) {
|
||||
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<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"))
|
||||
throw agi::fs::FileNotFound(std::string("Attempted creating dummy video provider with non-dummy filename"));
|
||||
return {};
|
||||
|
||||
std::vector<std::string> 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<VideoFrame> DummyVideoProvider::GetFrame(int) {
|
||||
return std::make_shared<VideoFrame>(data.data(), width, height, width * 4, false);
|
||||
}
|
||||
return agi::util::make_unique<DummyVideoProvider>(fps, frames, width, height, agi::Color(red, green, blue), pattern);
|
||||
}
|
|
@ -50,21 +50,7 @@ class DummyVideoProvider final : public VideoProvider {
|
|||
/// The data for the image returned for all frames
|
||||
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:
|
||||
/// 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
|
||||
|
|
|
@ -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 <libaegisub/fs.h>
|
||||
#include <libaegisub/util.h>
|
||||
|
||||
#include <wx/choicdlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
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) {
|
||||
// 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<VideoFrame> FFmpegSourceVideoProvider::GetFrame(int n) {
|
|||
|
||||
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 */
|
||||
|
|
|
@ -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
|
||||
// All rights reserved.
|
||||
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||
//
|
||||
// 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 <libaegisub/fs.h>
|
||||
#include <libaegisub/log.h>
|
||||
#include <libaegisub/util.h>
|
||||
|
||||
std::unique_ptr<VideoProvider> VideoProviderFactory::GetProvider(agi::fs::path const& video_file, std::string const& colormatrix) {
|
||||
std::vector<std::string> factories = GetClasses(OPT_GET("Video/Provider")->GetString());
|
||||
factories.insert(factories.begin(), "YUV4MPEG");
|
||||
factories.insert(factories.begin(), "Dummy");
|
||||
std::unique_ptr<VideoProvider> CreateDummyVideoProvider(agi::fs::path const&, std::string const&);
|
||||
std::unique_ptr<VideoProvider> CreateYUV4MPEGVideoProvider(agi::fs::path const&, std::string const&);
|
||||
std::unique_ptr<VideoProvider> CreateFFmpegSourceVideoProvider(agi::fs::path const&, std::string const&);
|
||||
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 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<VideoProviderCache>(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<VideoProvider> 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<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
|
||||
// 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 <libaegisub/fs_fwd.h>
|
||||
|
||||
class VideoProviderFactory final : public Factory<VideoProvider, agi::fs::path, std::string> {
|
||||
public:
|
||||
#include <memory>
|
||||
#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 void RegisterProviders();
|
||||
};
|
||||
|
|
|
@ -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 <boost/algorithm/string/case_conv.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
|
||||
/// @param filename The filename to open
|
||||
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename, std::string const&)
|
||||
: file(agi::util::make_unique<agi::read_file_mapping>(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<std::string> YUV4MPEGVideoProvider::ReadHeader(uint64_t &pos) {
|
||||
std::vector<std::string> tags;
|
||||
if (pos >= file->size())
|
||||
if (pos >= file.size())
|
||||
return tags;
|
||||
|
||||
auto len = std::min<uint64_t>(YUV4MPEG_HEADER_MAXLEN, file->size() - pos);
|
||||
auto buff = file->read(pos, len);
|
||||
auto len = std::min<uint64_t>(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<VideoFrame> YUV4MPEGVideoProvider::GetFrame(int n) {
|
|||
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_v = src_u + chroma_sz;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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