2014-03-24 15:05:01 +01:00
|
|
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
2006-02-24 09:30:08 +01:00
|
|
|
//
|
2014-03-24 15:05:01 +01:00
|
|
|
// 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.
|
2006-02-24 09:30:08 +01:00
|
|
|
//
|
2014-03-24 15:05:01 +01:00
|
|
|
// 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.
|
2006-02-24 09:30:08 +01:00
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
2009-01-04 07:31:48 +01:00
|
|
|
#include "config.h"
|
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
#include "video_provider_manager.h"
|
2010-06-09 01:21:39 +02:00
|
|
|
|
2014-03-24 15:05:01 +01:00
|
|
|
#include "include/aegisub/video_provider.h"
|
2013-01-07 02:50:09 +01:00
|
|
|
#include "options.h"
|
2007-01-21 07:30:19 +01:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
#include <libaegisub/fs.h>
|
|
|
|
#include <libaegisub/log.h>
|
2013-06-08 06:19:40 +02:00
|
|
|
#include <libaegisub/util.h>
|
2007-01-21 07:30:19 +01:00
|
|
|
|
2014-03-24 15:05:01 +01:00
|
|
|
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);
|
|
|
|
}
|
2007-01-21 07:30:19 +01:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
bool found = false;
|
|
|
|
bool supported = false;
|
2010-08-02 08:32:01 +02:00
|
|
|
std::string errors;
|
|
|
|
errors.reserve(1024);
|
2013-01-04 16:01:50 +01:00
|
|
|
|
2014-03-24 15:05:01 +01:00
|
|
|
for (auto factory : sorted) {
|
2010-12-29 20:35:45 +01:00
|
|
|
std::string err;
|
2006-02-24 09:43:44 +01:00
|
|
|
try {
|
2014-03-24 15:05:01 +01:00
|
|
|
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);
|
2010-08-02 08:32:01 +02:00
|
|
|
}
|
2013-01-04 16:01:50 +01:00
|
|
|
catch (agi::fs::FileNotFound const&) {
|
|
|
|
err = "file not found.";
|
2010-08-02 08:32:01 +02:00
|
|
|
// Keep trying other providers as this one may just not be able to
|
|
|
|
// open a valid path
|
|
|
|
}
|
|
|
|
catch (VideoNotSupported const&) {
|
2013-01-04 16:01:50 +01:00
|
|
|
found = true;
|
|
|
|
err = "video is not in a supported format.";
|
2010-08-02 08:32:01 +02:00
|
|
|
}
|
|
|
|
catch (VideoOpenError const& ex) {
|
2013-01-04 16:01:50 +01:00
|
|
|
supported = true;
|
|
|
|
err = ex.GetMessage();
|
2006-02-24 09:43:44 +01:00
|
|
|
}
|
2010-12-29 20:35:45 +01:00
|
|
|
catch (agi::vfr::Error const& ex) {
|
2013-01-04 16:01:50 +01:00
|
|
|
supported = true;
|
|
|
|
err = ex.GetMessage();
|
2010-12-29 20:35:45 +01:00
|
|
|
}
|
2013-01-04 16:01:50 +01:00
|
|
|
|
2014-03-24 15:05:01 +01:00
|
|
|
errors += std::string(factory->name) + ": " + err + "\n";
|
|
|
|
LOG_D("manager/video/provider") << factory->name << ": " << err;
|
2006-02-24 09:43:44 +01:00
|
|
|
}
|
2006-02-24 09:30:08 +01:00
|
|
|
|
2010-08-02 08:32:01 +02:00
|
|
|
// No provider could open the file
|
2014-03-24 15:05:01 +01:00
|
|
|
LOG_E("manager/video/provider") << "Could not open " << filename;
|
|
|
|
std::string msg = "Could not open " + filename.string() + ":\n" + errors;
|
2010-08-02 08:32:01 +02:00
|
|
|
|
2014-03-24 15:05:01 +01:00
|
|
|
if (!found) throw agi::fs::FileNotFound(filename.string());
|
2013-01-04 16:01:50 +01:00
|
|
|
if (!supported) throw VideoNotSupported(msg);
|
2010-08-02 08:32:01 +02:00
|
|
|
throw VideoOpenError(msg);
|
2006-02-24 09:30:08 +01:00
|
|
|
}
|