+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
#include "../../stdafx.h"\r
\r
#include "util.h"\r
if(desc.pix_fmt == core::pixel_format::invalid)\r
{\r
auto pix_fmt = static_cast<PixelFormat>(decoded_frame->format);\r
+ auto target_pix_fmt = PIX_FMT_BGRA;\r
+\r
+ if(pix_fmt == PIX_FMT_UYVY422)\r
+ target_pix_fmt = PIX_FMT_YUV422P;\r
+ else if(pix_fmt == PIX_FMT_YUYV422)\r
+ target_pix_fmt = PIX_FMT_YUV422P;\r
+ else if(pix_fmt == PIX_FMT_UYYVYY411)\r
+ target_pix_fmt = PIX_FMT_YUV411P;\r
+ else if(pix_fmt == PIX_FMT_YUV420P10)\r
+ target_pix_fmt = PIX_FMT_YUV420P;\r
+ else if(pix_fmt == PIX_FMT_YUV422P10)\r
+ target_pix_fmt = PIX_FMT_YUV422P;\r
+ else if(pix_fmt == PIX_FMT_YUV444P10)\r
+ target_pix_fmt = PIX_FMT_YUV444P;\r
+ \r
+ auto target_desc = get_pixel_format_desc(target_pix_fmt, width, height);\r
\r
- write = frame_factory->create_frame(tag, get_pixel_format_desc(PIX_FMT_BGRA, width, height));\r
+ write = frame_factory->create_frame(tag, target_desc);\r
write->set_type(get_mode(*decoded_frame));\r
\r
std::shared_ptr<SwsContext> sws_context;\r
\r
//CASPAR_LOG(warning) << "Hardware accelerated color transform not supported.";\r
\r
- size_t key = width << 20 | height << 8 | pix_fmt;\r
+ size_t key = ((width << 22) & 0xFFC00000) | ((height << 6) & 0x003FC000) | ((pix_fmt << 7) & 0x00007F00) | ((target_pix_fmt << 0) & 0x0000007F);\r
\r
auto& pool = sws_contexts_[key];\r
\r
if(!pool.try_pop(sws_context))\r
{\r
double param;\r
- sws_context.reset(sws_getContext(width, height, pix_fmt, width, height, PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, ¶m), sws_freeContext);\r
+ sws_context.reset(sws_getContext(width, height, pix_fmt, width, height, target_pix_fmt, SWS_BILINEAR, nullptr, nullptr, ¶m), sws_freeContext);\r
}\r
\r
if(!sws_context)\r
BOOST_THROW_EXCEPTION(operation_failed() << msg_info("Could not create software scaling context.") << \r
boost::errinfo_api_function("sws_getContext"));\r
} \r
-\r
- // Use sws_scale when provided colorspace has no hw-accel.\r
+ \r
safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free); \r
avcodec_get_frame_defaults(av_frame.get()); \r
- auto size = avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), write->image_data().begin(), PIX_FMT_BGRA, width, height);\r
- CASPAR_VERIFY(size == write->image_data().size()); \r
+ if(target_pix_fmt == PIX_FMT_BGRA)\r
+ {\r
+ auto size = avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), write->image_data().begin(), PIX_FMT_BGRA, width, height);\r
+ CASPAR_VERIFY(size == write->image_data().size()); \r
+ }\r
+ else\r
+ {\r
+ av_frame->width = width;\r
+ av_frame->height = height;\r
+ for(size_t n = 0; n < target_desc.planes.size(); ++n)\r
+ {\r
+ av_frame->data[n] = write->image_data(n).begin();\r
+ av_frame->linesize[n] = target_desc.planes[n].linesize;\r
+ }\r
+ }\r
\r
sws_scale(sws_context.get(), decoded_frame->data, decoded_frame->linesize, 0, height, av_frame->data, av_frame->linesize); \r
pool.push(sws_context);\r
\r
- write->commit();\r
+ write->commit(); \r
}\r
else\r
{\r
\r
return boost::lexical_cast<std::wstring>(width) + L"x" + boost::lexical_cast<std::wstring>(height) + (!interlaced ? L"p" : L"i") + fps_ss.str();\r
}\r
+\r
+bool is_valid_file(const std::wstring filename)\r
+{ \r
+ auto filename2 = narrow(filename);\r
+\r
+ std::ifstream file(filename2);\r
+\r
+ std::vector<unsigned char> buf;\r
+ for(auto file_it = std::istreambuf_iterator<char>(file); file_it != std::istreambuf_iterator<char>() && buf.size() < 2048; ++file_it)\r
+ buf.push_back(*file_it);\r
+\r
+ if(buf.empty())\r
+ return nullptr;\r
+\r
+ AVProbeData pb;\r
+ pb.filename = filename2.c_str();\r
+ pb.buf = buf.data();\r
+ pb.buf_size = buf.size();\r
+\r
+ int score = 0;\r
+ return av_probe_input_format2(&pb, true, &score) != nullptr;\r
+}\r
+\r
+std::wstring probe_stem(const std::wstring stem)\r
+{\r
+ auto stem2 = boost::filesystem2::wpath(stem);\r
+ auto dir = stem2.parent_path();\r
+ for(auto it = boost::filesystem2::wdirectory_iterator(dir); it != boost::filesystem2::wdirectory_iterator(); ++it)\r
+ {\r
+ if(boost::iequals(it->path().stem(), stem2.filename()) && is_valid_file(it->path().file_string()))\r
+ return it->path().file_string();\r
+ }\r
+ return L"";\r
+}\r
//\r
//void av_dup_frame(AVFrame* frame)\r
//{\r