#include <core/frame/draw_frame.h>
#include <core/frame/frame_factory.h>
#include <core/frame/pixel_format.h>
+#include <core/frame/audio_channel_layout.h>
#include <core/monitor/monitor.h>
+#include <core/help/help_sink.h>
+#include <core/help/help_repository.h>
#include <common/env.h>
#include <common/log.h>
auto width = FreeImage_GetWidth(bitmap.get());
auto height = FreeImage_GetHeight(bitmap.get());
desc.planes.push_back(core::pixel_format_desc::plane(width, height, 4));
- auto frame = frame_factory->create_frame(bitmap.get(), desc);
+ auto frame = frame_factory->create_frame(bitmap.get(), desc, core::audio_channel_layout::invalid());
std::copy_n(
FreeImage_GetBits(bitmap.get()),
core::draw_frame frame_ = core::draw_frame::empty();
core::constraints constraints_;
- image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& description)
+ image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& description, bool thumbnail_mode)
: description_(description)
, frame_factory_(frame_factory)
{
load(load_image(description_));
- CASPAR_LOG(info) << print() << L" Initialized";
+ if (thumbnail_mode)
+ CASPAR_LOG(debug) << print() << L" Initialized";
+ else
+ CASPAR_LOG(info) << print() << L" Initialized";
}
image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const void* png_data, size_t size)
void load(const std::shared_ptr<FIBITMAP>& bitmap)
{
FreeImage_FlipVertical(bitmap.get());
+ auto longest_side = static_cast<int>(std::max(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get())));
+
+ if (longest_side > frame_factory_->get_max_frame_size())
+ CASPAR_THROW_EXCEPTION(user_error() << msg_info("Image too large for texture"));
+
core::pixel_format_desc desc;
desc.format = core::pixel_format::bgra;
desc.planes.push_back(core::pixel_format_desc::plane(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()), 4));
- auto frame = frame_factory_->create_frame(this, desc);
+ auto frame = frame_factory_->create_frame(this, desc, core::audio_channel_layout::invalid());
std::copy_n(FreeImage_GetBits(bitmap.get()), frame.image_data().size(), frame.image_data().begin());
frame_ = core::draw_frame(std::move(frame));
return frame_;
}
- core::draw_frame create_thumbnail_frame() override
- {
- return frame_;
- }
-
core::constraints& pixel_constraints() override
{
return constraints_;
}
};
-spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+void describe_producer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"Loads a still image.");
+ sink.syntax(L"{[image_file:string]},{[PNG_BASE64] [encoded:string]}");
+ sink.para()->text(L"Loads a still image, either from disk or via a base64 encoded image submitted via AMCP.");
+ sink.para()->text(L"Examples:");
+ sink.example(L">> PLAY 1-10 image_file", L"Plays an image from the media folder.");
+ sink.example(L">> PLAY 1-10 [PNG_BASE64] data...", L"Plays a PNG image transferred as a base64 encoded string.");
+}
+
+static const auto g_extensions = {
+ L".png",
+ L".tga",
+ L".bmp",
+ L".jpg",
+ L".jpeg",
+ L".gif",
+ L".tiff",
+ L".tif",
+ L".jp2",
+ L".jpx",
+ L".j2k",
+ L".j2c"
+};
+
+spl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
{
- static const auto extensions = {
- L".png",
- L".tga",
- L".bmp",
- L".jpg",
- L".jpeg",
- L".gif",
- L".tiff",
- L".tif",
- L".jp2",
- L".jpx",
- L".j2k",
- L".j2c"
- };
-
- if (boost::iequals(params[0], L"[IMG_SEQUENCE]"))
+
+ if (boost::iequals(params.at(0), L"[IMG_SEQUENCE]"))
{
if (params.size() != 2)
return core::frame_producer::empty();
- auto dir = boost::filesystem::path(env::media_folder() + params[1]).parent_path();
- auto basename = boost::filesystem::basename(params[1]);
+ auto dir = boost::filesystem::path(env::media_folder() + params.at(1)).parent_path();
+ auto basename = boost::filesystem::basename(params.at(1));
std::set<std::wstring> files;
boost::filesystem::directory_iterator end;
auto extension = it->path().extension().wstring();
- if (std::find_if(extensions.begin(), extensions.end(), ieq(extension)) == extensions.end())
+ if (std::find_if(g_extensions.begin(), g_extensions.end(), ieq(extension)) == g_extensions.end())
continue;
files.insert(it->path().wstring());
for (auto& file : files)
{
- auto frame = load_image(frame_factory, file);
+ auto frame = load_image(dependencies.frame_factory, file);
if (width == -1)
{
return core::create_const_producer(std::move(frames), width, height);
}
- else if(boost::iequals(params[0], L"[PNG_BASE64]"))
+ else if(boost::iequals(params.at(0), L"[PNG_BASE64]"))
{
if (params.size() < 2)
return core::frame_producer::empty();
- auto png_data = from_base64(std::string(params[1].begin(), params[1].end()));
+ auto png_data = from_base64(std::string(params.at(1).begin(), params.at(1).end()));
- return spl::make_shared<image_producer>(frame_factory, png_data.data(), png_data.size());
+ return spl::make_shared<image_producer>(dependencies.frame_factory, png_data.data(), png_data.size());
}
- std::wstring filename = env::media_folder() + params[0];
+ std::wstring filename = env::media_folder() + params.at(0);
- auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool
+ auto ext = std::find_if(g_extensions.begin(), g_extensions.end(), [&](const std::wstring& ex) -> bool
{
- auto file = caspar::find_case_insensitive(boost::filesystem::path(filename).replace_extension(ex).wstring());
+ auto file = caspar::find_case_insensitive(boost::filesystem::path(filename).wstring() + ex);
return static_cast<bool>(file);
});
- if(ext == extensions.end())
+ if(ext == g_extensions.end())
return core::frame_producer::empty();
- return spl::make_shared<image_producer>(frame_factory, *caspar::find_case_insensitive(filename + *ext));
+ return spl::make_shared<image_producer>(dependencies.frame_factory, *caspar::find_case_insensitive(filename + *ext), false);
}
-spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+core::draw_frame create_thumbnail(const core::frame_producer_dependencies& dependencies, const std::wstring& media_file)
{
- return caspar::image::create_producer(frame_factory, format_desc, params);
+ std::wstring filename = env::media_folder() + media_file;
+
+ auto ext = std::find_if(g_extensions.begin(), g_extensions.end(), [&](const std::wstring& ex) -> bool
+ {
+ auto file = caspar::find_case_insensitive(boost::filesystem::path(filename).wstring() + ex);
+
+ return static_cast<bool>(file);
+ });
+
+ if (ext == g_extensions.end())
+ return core::draw_frame::empty();
+
+ spl::shared_ptr<core::frame_producer> producer = spl::make_shared<image_producer>(
+ dependencies.frame_factory,
+ *caspar::find_case_insensitive(filename + *ext),
+ true);
+
+ return producer->receive();
}
+
}}