#include <boost/range/algorithm_ext/erase.hpp>\r
#include <boost/thread/future.hpp>\r
\r
-#include <intrin.h>\r
-#include <stdint.h>\r
#include <algorithm>\r
+#include <stdint.h>\r
#include <vector>\r
\r
#if defined(_MSC_VER)\r
\r
void convert(std::vector<item>& items, int width, int height)\r
{\r
- typedef std::map<std::vector<spl::shared_ptr<host_buffer>>, std::shared_ptr<host_buffer>> buffer_map_t;\r
- typedef std::map<std::vector<spl::shared_ptr<host_buffer>>, core::pixel_format_desc> pix_desc_map_t;\r
+ std::set<std::vector<spl::shared_ptr<host_buffer>>> buffers;\r
\r
- buffer_map_t buffer_map;\r
- pix_desc_map_t pix_desc_map;\r
BOOST_FOREACH(auto& item, items)\r
- {\r
- buffer_map[item.buffers] = nullptr;\r
- pix_desc_map[item.buffers] = item.pix_desc;\r
- }\r
+ buffers.insert(item.buffers);\r
+ \r
+ tbb::parallel_for_each(buffers.begin(), buffers.end(), std::bind(&image_renderer::do_convert, this, std::ref(items), std::placeholders::_1, width, height)); \r
+ }\r
\r
- // TODO: Don't convert buffers multiple times just because they are in different items due to e.g. interlacing.\r
- tbb::parallel_for_each(buffer_map.begin(), buffer_map.end(), [&](buffer_map_t::value_type& pair)\r
- {\r
- auto buffers = pair.first;\r
- auto pix_desc = pix_desc_map[buffers];\r
+ void do_convert(std::vector<item>& items, const std::vector<spl::shared_ptr<host_buffer>>& buffers, int width, int height)\r
+ { \r
+ auto pix_desc = std::find_if(items.begin(), items.end(), [&](const item& item){return item.buffers == buffers;})->pix_desc;\r
\r
- if(pix_desc.format == core::pixel_format::bgra && \r
- pix_desc.planes.at(0).width == width &&\r
- pix_desc.planes.at(0).height == height)\r
- return;\r
+ if(pix_desc.format == core::pixel_format::bgra && \r
+ pix_desc.planes.at(0).width == width &&\r
+ pix_desc.planes.at(0).height == height)\r
+ return;\r
\r
- auto input_av_frame = ffmpeg::make_av_frame(buffers, pix_desc);\r
+ auto input_av_frame = ffmpeg::make_av_frame(buffers, pix_desc);\r
\r
- int key = ((input_av_frame->width << 22) & 0xFFC00000) | ((input_av_frame->height << 6) & 0x003FC000) | ((input_av_frame->format << 7) & 0x00007F00);\r
+ int key = ((input_av_frame->width << 22) & 0xFFC00000) | ((input_av_frame->height << 6) & 0x003FC000) | ((input_av_frame->format << 7) & 0x00007F00);\r
\r
- auto& pool = sws_contexts_[key];\r
+ auto& pool = sws_contexts_[key];\r
\r
- std::shared_ptr<SwsContext> sws_context;\r
- if(!pool.try_pop(sws_context))\r
- {\r
- double param;\r
- sws_context.reset(sws_getContext(input_av_frame->width, input_av_frame->height, static_cast<PixelFormat>(input_av_frame->format), width, height, PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, ¶m), sws_freeContext);\r
- }\r
+ std::shared_ptr<SwsContext> sws_context;\r
+ if(!pool.try_pop(sws_context))\r
+ {\r
+ double param;\r
+ sws_context.reset(sws_getContext(input_av_frame->width, input_av_frame->height, static_cast<PixelFormat>(input_av_frame->format), width, height, PIX_FMT_BGRA, 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.") << boost::errinfo_api_function("sws_getContext")); \r
+ if(!sws_context) \r
+ BOOST_THROW_EXCEPTION(operation_failed() << msg_info("Could not create software scaling context.") << boost::errinfo_api_function("sws_getContext")); \r
\r
- auto dest = spl::make_shared<host_buffer>(width*height*4);\r
+ auto dest = spl::make_shared<host_buffer>(width*height*4);\r
\r
- {\r
- spl::shared_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free); \r
- avcodec_get_frame_defaults(av_frame.get()); \r
- avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), dest->data(), PIX_FMT_BGRA, width, height);\r
+ {\r
+ spl::shared_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free); \r
+ avcodec_get_frame_defaults(av_frame.get()); \r
+ avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), dest->data(), PIX_FMT_BGRA, width, height);\r
\r
- sws_scale(sws_context.get(), input_av_frame->data, input_av_frame->linesize, 0, input_av_frame->height, av_frame->data, av_frame->linesize); \r
- pool.push(sws_context);\r
- }\r
-\r
- pair.second = dest;\r
- });\r
- \r
- BOOST_FOREACH(auto& item, items)\r
- { \r
- item.buffers = boost::assign::list_of(spl::make_shared_ptr(buffer_map[item.buffers]));\r
- item.pix_desc = core::pixel_format_desc(core::pixel_format::bgra);\r
- item.pix_desc.planes = boost::assign::list_of(core::pixel_format_desc::plane(width, height, 4));\r
+ sws_scale(sws_context.get(), input_av_frame->data, input_av_frame->linesize, 0, input_av_frame->height, av_frame->data, av_frame->linesize); \r
+ pool.push(sws_context);\r
}\r
+ \r
+ BOOST_FOREACH(auto& item, items)\r
+ {\r
+ if(item.buffers == buffers)\r
+ {\r
+ item.buffers = boost::assign::list_of(dest);\r
+ item.pix_desc = core::pixel_format_desc(core::pixel_format::bgra);\r
+ item.pix_desc.planes = boost::assign::list_of(core::pixel_format_desc::plane(width, height, 4));\r
+ }\r
+ } \r
}\r
};\r
\r