]> git.sesse.net Git - casparcg/commitdiff
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 11 Jan 2011 17:45:00 +0000 (17:45 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 11 Jan 2011 17:45:00 +0000 (17:45 +0000)
common/common.vcxproj
common/common.vcxproj.filters
common/memory/page_locked_allocator.h [new file with mode: 0644]
core/consumer/bluefish/bluefish_consumer.cpp
core/consumer/bluefish/memory.h
core/producer/ffmpeg/video/video_decoder.cpp

index 79428d03863ccdd4e47e30df5c68bf50ef564dd0..4c158dcf79b4b003ef2bbb8a8178d7f4ff936608 100644 (file)
     <ClInclude Include="io\ProtocolStrategy.h" />\r
     <ClInclude Include="io\SocketInfo.h" />\r
     <ClInclude Include="log\log.h" />\r
+    <ClInclude Include="memory\page_locked_allocator.h" />\r
     <ClInclude Include="stdafx.h" />\r
     <ClInclude Include="utility\safe_ptr.h" />\r
     <ClInclude Include="utility\string_convert.h" />\r
index 4ac54811836ad69578b9d9c822fb0a33785716f3..525a264a9571b575c2c5bd2d7194c33a4e5d3641 100644 (file)
@@ -32,6 +32,9 @@
     <Filter Include="Afx">\r
       <UniqueIdentifier>{9250809a-3410-418d-95ca-ff2dcb6f0578}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="Source\memory">\r
+      <UniqueIdentifier>{9259676d-c225-4422-a50e-30d152d78dc2}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="io\SocketInfo.cpp">\r
     <ClInclude Include="gl\gl_check.h">\r
       <Filter>Source\gl</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="memory\page_locked_allocator.h">\r
+      <Filter>Source\memory</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
diff --git a/common/memory/page_locked_allocator.h b/common/memory/page_locked_allocator.h
new file mode 100644 (file)
index 0000000..9df6c91
--- /dev/null
@@ -0,0 +1,111 @@
+#pragma once\r
+\r
+#include <unordered_map>\r
+#include <tbb/mutex.h>\r
+\r
+namespace caspar\r
+{\r
+       \r
+template <class T>\r
+class page_locked_allocator\r
+{\r
+public:\r
+       typedef size_t    size_type;\r
+       typedef ptrdiff_t difference_type;\r
+       typedef T*        pointer;\r
+       typedef const T*  const_pointer;\r
+       typedef T&        reference;\r
+       typedef const T&  const_reference;\r
+       typedef T         value_type;\r
+\r
+       page_locked_allocator() {}\r
+       page_locked_allocator(const page_locked_allocator&) {}\r
+  \r
+       pointer allocate(size_type n, const void * = 0) \r
+       {\r
+               tbb::mutex::scoped_lock lock(get().mutex);\r
+\r
+               size_type size = n * sizeof(T);         \r
+               if(get().free < size)\r
+                       allocate_store(size);\r
+\r
+               auto p = ::VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);\r
+               if(!p)\r
+                       throw std::bad_alloc();\r
+\r
+               if(::VirtualLock(p, size) == 0) \r
+               {\r
+                       ::VirtualFree(p, 0, MEM_RELEASE);\r
+                       throw std::bad_alloc();\r
+               }\r
+               \r
+               get().free -= size;\r
+               get().map[p] = size;\r
+               return reinterpret_cast<T*>(p);\r
+       }\r
+  \r
+       void deallocate(void* p, size_type) \r
+       {\r
+               tbb::mutex::scoped_lock lock(get().mutex);\r
+\r
+               if(!p || get().map.find(p) == get().map.end())\r
+                       return;\r
+\r
+               try\r
+               {\r
+                       ::VirtualFree(p, 0, MEM_RELEASE);\r
+                       get().free += get().map[p];\r
+                       get().map.erase(p);\r
+               }\r
+               catch(...){}            \r
+       }\r
+\r
+       pointer           address(reference x) const { return &x; }\r
+       const_pointer     address(const_reference x) const { return &x; }\r
+       page_locked_allocator<T>&  operator=(const page_locked_allocator&) { return *this; }\r
+       void              construct(pointer p, const T& val) { new ((T*) p) T(val); }\r
+       void              destroy(pointer p) { p->~T(); }\r
+\r
+       size_type         max_size() const { return size_t(-1); }\r
+\r
+       template <class U>\r
+       struct rebind { typedef page_locked_allocator<U> other; };\r
+\r
+       template <class U>\r
+       page_locked_allocator(const page_locked_allocator<U>&) {}\r
+\r
+       template <class U>\r
+       page_locked_allocator& operator=(const page_locked_allocator<U>&) { return *this; }\r
+\r
+private:\r
+\r
+       void allocate_store(size_type size)\r
+       {               \r
+               SIZE_T workingSetMinSize = 0, workingSetMaxSize = 0;\r
+               if(::GetProcessWorkingSetSize(::GetCurrentProcess(), &workingSetMinSize, &workingSetMaxSize))\r
+               {                       \r
+                       workingSetMinSize += size;\r
+                       workingSetMaxSize += size;\r
+\r
+                       if(!::SetProcessWorkingSetSize(::GetCurrentProcess(), workingSetMinSize, workingSetMaxSize))            \r
+                               throw std::bad_alloc();         \r
+\r
+                       get().free += size;\r
+               }\r
+       }\r
+\r
+       struct impl\r
+       {\r
+               impl() : free(0){}\r
+               std::unordered_map<void*, size_type> map;\r
+               size_type free;\r
+               tbb::mutex mutex;\r
+       };\r
+\r
+       static impl& get()\r
+       {\r
+               static impl i;\r
+               return i;\r
+       }\r
+};\r
+}
\ No newline at end of file
index edbceaa4c2b3ab5088fe02bdba3f7f02ba9d9b5d..0d7726708c7dda7effe86ff4d7d1e51471af5a9f 100644 (file)
@@ -54,11 +54,9 @@ struct consumer::implementation : boost::noncopyable
        EVideoMode              vid_fmt_; \r
        unsigned long   res_fmt_; \r
        unsigned long   engine_mode_;\r
+       \r
+       std::array<blue_dma_buffer_ptr, 3> reserved_frames_;    \r
 \r
-       std::shared_ptr<const read_frame> transferring_frame_;\r
-\r
-       std::array<page_locked_buffer_ptr, 3> hanc_buffers_;\r
-       int current_id_;\r
        bool embed_audio_;\r
 \r
 public:\r
@@ -71,7 +69,6 @@ public:
                , vid_fmt_(VID_FMT_INVALID) \r
                , res_fmt_(RES_FMT_NORMAL) \r
                , engine_mode_(VIDEO_ENGINE_FRAMESTORE)         \r
-               , current_id_(0)\r
                , embed_audio_(embed_audio)\r
        {\r
                                \r
@@ -161,9 +158,8 @@ public:
 \r
                enable_video_output();\r
                                                \r
-               page_locked_buffer::reserve_working_size(MAX_HANC_BUFFER_SIZE * hanc_buffers_.size());          \r
-               for(size_t n = 0; n < hanc_buffers_.size(); ++n)\r
-                       hanc_buffers_[n] = std::make_shared<page_locked_buffer>(MAX_HANC_BUFFER_SIZE);\r
+               for(size_t n = 0; n < reserved_frames_.size(); ++n)\r
+                       reserved_frames_[n] = std::make_shared<blue_dma_buffer>(format_desc_.size, n);          \r
                                \r
                executor_.start();\r
 \r
@@ -174,7 +170,6 @@ public:
 \r
        ~implementation()\r
        {\r
-               page_locked_buffer::unreserve_working_size(MAX_HANC_BUFFER_SIZE * hanc_buffers_.size());                \r
                disable_video_output();\r
 \r
                if(sdk_)\r
@@ -197,52 +192,52 @@ public:
 \r
        void send(const safe_ptr<const read_frame>& frame)\r
        {                       \r
-               static size_t audio_samples = static_cast<size_t>(48000.0 / format_desc_.fps);\r
-               static size_t audio_nchannels = 2;\r
-               static std::vector<short> silence(audio_samples*audio_nchannels*2, 0);\r
+               static std::vector<short> silence(MAX_HANC_BUFFER_SIZE, 0);\r
+               \r
+               size_t audio_samples = static_cast<size_t>(48000.0 / format_desc_.fps);\r
+               size_t audio_nchannels = 2;\r
                \r
                active_.get();\r
                active_ = executor_.begin_invoke([=]\r
                {\r
                        try\r
                        {\r
-                               auto hanc = hanc_buffers_.front();              \r
-                               std::rotate(hanc_buffers_.begin(), hanc_buffers_.begin() + 1, hanc_buffers_.end());\r
+                               std::copy_n(frame->image_data().begin(), frame->image_data().size(), reserved_frames_.front()->image_data());\r
 \r
-                               unsigned long fieldCount = 0;\r
-                               sdk_->wait_output_video_synch(UPD_FMT_FRAME, fieldCount);\r
+                               unsigned long n_field = 0;\r
+                               sdk_->wait_output_video_synch(UPD_FMT_FRAME, n_field);\r
                                \r
                                if(embed_audio_)\r
                                {               \r
                                        auto frame_audio_data = frame->audio_data().empty() ? silence.data() : const_cast<short*>(frame->audio_data().begin());\r
 \r
-                                       encode_hanc(reinterpret_cast<BLUE_UINT32*>(hanc->data()), frame_audio_data, audio_samples, audio_nchannels);\r
+                                       encode_hanc(reinterpret_cast<BLUE_UINT32*>(reserved_frames_.front()->hanc_data()), frame_audio_data, audio_samples, audio_nchannels);\r
                                                                \r
-                                       sdk_->system_buffer_write_async(const_cast<unsigned char*>(frame->image_data().begin()), \r
-                                                                                                       frame->image_data().size(), \r
+                                       sdk_->system_buffer_write_async(const_cast<unsigned char*>(reserved_frames_.front()->image_data()), \r
+                                                                                                       reserved_frames_.front()->image_size(), \r
                                                                                                        nullptr, \r
-                                                                                                       BlueImage_HANC_DMABuffer(current_id_, BLUE_DATA_IMAGE));\r
+                                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE));\r
 \r
-                                       sdk_->system_buffer_write_async(hanc->data(),\r
-                                                                                                       hanc->size(), \r
+                                       sdk_->system_buffer_write_async(reserved_frames_.front()->hanc_data(),\r
+                                                                                                       reserved_frames_.front()->hanc_size(), \r
                                                                                                        nullptr,                 \r
-                                                                                                       BlueImage_HANC_DMABuffer(current_id_, BLUE_DATA_HANC));\r
+                                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_HANC));\r
 \r
-                                       if(BLUE_FAIL(sdk_->render_buffer_update(BlueBuffer_Image_HANC(current_id_))))\r
+                                       if(BLUE_FAIL(sdk_->render_buffer_update(BlueBuffer_Image_HANC(reserved_frames_.front()->id()))))\r
                                                CASPAR_LOG(trace) << TEXT("BLUEFISH: render_buffer_update failed");\r
                                }\r
                                else\r
                                {\r
-                                       sdk_->system_buffer_write_async(const_cast<unsigned char*>(frame->image_data().begin()),\r
-                                                                                                       frame->image_data().size(), \r
+                                       sdk_->system_buffer_write_async(const_cast<unsigned char*>(reserved_frames_.front()->image_data()),\r
+                                                                                                       reserved_frames_.front()->image_size(), \r
                                                                                                        nullptr,                 \r
-                                                                                                       BlueImage_DMABuffer(current_id_, BLUE_DATA_IMAGE));\r
+                                                                                                       BlueImage_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE));\r
                        \r
-                                       if(BLUE_FAIL(sdk_->render_buffer_update(BlueBuffer_Image(current_id_))))\r
+                                       if(BLUE_FAIL(sdk_->render_buffer_update(BlueBuffer_Image(reserved_frames_.front()->id()))))\r
                                                CASPAR_LOG(trace) << TEXT("BLUEFISH: render_buffer_update failed");\r
                                }\r
 \r
-                               transferring_frame_ = frame;\r
+                               std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
                        }\r
                        catch(...)\r
                        {\r
@@ -263,8 +258,11 @@ public:
                \r
                hanc_stream_info_struct hanc_stream_info;\r
                memset(&hanc_stream_info, 0, sizeof(hanc_stream_info));\r
-\r
-               std::fill_n(hanc_stream_info.AudioDBNArray, sizeof(hanc_stream_info.AudioDBNArray)/sizeof(hanc_stream_info.AudioDBNArray[0]), -1);\r
+               \r
+               hanc_stream_info.AudioDBNArray[0] = -1;\r
+               hanc_stream_info.AudioDBNArray[1] = -1;\r
+               hanc_stream_info.AudioDBNArray[2] = -1;\r
+               hanc_stream_info.AudioDBNArray[3] = -1;\r
                hanc_stream_info.hanc_data_ptr = hanc_data;\r
                hanc_stream_info.video_mode = vid_fmt_;\r
                \r
index 54baef178d4935bd2af40c4222243aa411e5fd22..00b8d3bcd7af36051d83c49034c64fd609e09904 100644 (file)
@@ -5,80 +5,43 @@
 #include <BlueVelvet4.h>\r
 #include "../../format/video_format.h"\r
 \r
+#include <common/memory/page_locked_allocator.h>\r
+\r
 #include <tbb/mutex.h>\r
+#include <tbb/recursive_mutex.h>\r
+\r
+#include <unordered_map>\r
 \r
 namespace caspar { namespace core { namespace bluefish {\r
        \r
 static const size_t MAX_HANC_BUFFER_SIZE = 256*1024;\r
 static const size_t MAX_VBI_BUFFER_SIZE = 36*1920*4;\r
 \r
-struct page_locked_buffer\r
+struct blue_dma_buffer\r
 {\r
 public:\r
-       page_locked_buffer(size_t size) \r
-               : size_(size)\r
-               , data_(static_cast<unsigned char*>(::VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))\r
-       {\r
-               if(!data_)      \r
-                       BOOST_THROW_EXCEPTION(bluefish_exception() << msg_info("Failed to allocate memory for paged locked buffer."));  \r
-               if(::VirtualLock(data_.get(), size_) == 0)      \r
-                       BOOST_THROW_EXCEPTION(bluefish_exception() << msg_info("Failed to lock memory for paged locked buffer."));\r
-       }\r
-       \r
-       static void reserve_working_size(size_t size)\r
-       {\r
-               auto lock = get_lock();\r
-               SIZE_T workingSetMinSize = 0, workingSetMaxSize = 0;\r
-               if(::GetProcessWorkingSetSize(::GetCurrentProcess(), &workingSetMinSize, &workingSetMaxSize))\r
-               {\r
-                       CASPAR_LOG(debug) << TEXT("WorkingSet size: min = ") << workingSetMinSize << TEXT(", max = ") << workingSetMaxSize;\r
-                       \r
-                       workingSetMinSize += size;\r
-                       workingSetMaxSize += size;\r
-\r
-                       if(!::SetProcessWorkingSetSize(::GetCurrentProcess(), workingSetMinSize, workingSetMaxSize))            \r
-                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed set workingset."));                \r
-               }\r
-       }\r
-\r
-       static void unreserve_working_size(size_t size)\r
-       {\r
-               auto lock = get_lock();\r
-               SIZE_T workingSetMinSize = 0, workingSetMaxSize = 0;\r
-               if(::GetProcessWorkingSetSize(::GetCurrentProcess(), &workingSetMinSize, &workingSetMaxSize))\r
-               {\r
-                       CASPAR_LOG(debug) << TEXT("WorkingSet size: min = ") << workingSetMinSize << TEXT(", max = ") << workingSetMaxSize;\r
+       blue_dma_buffer(int image_size, int id) \r
+               : id_(id)\r
+               , image_size_(image_size)\r
+               , hanc_size_(256*1024)\r
+               , image_buffer_(image_size_)\r
+               , hanc_buffer_(hanc_size_){}\r
                        \r
-                       workingSetMinSize += static_cast<SIZE_T>(static_cast<int>(workingSetMinSize) - static_cast<int>(size));\r
-                       workingSetMaxSize += static_cast<SIZE_T>(static_cast<int>(workingSetMaxSize) - static_cast<int>(size));\r
+       int id() const {return id_;}\r
 \r
-                       if(!::SetProcessWorkingSetSize(::GetCurrentProcess(), workingSetMinSize, workingSetMaxSize))            \r
-                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed set workingset."));                \r
-               }\r
-       }\r
+       PBYTE image_data() { return image_buffer_.data(); }\r
+       PBYTE hanc_data() { return hanc_buffer_.data(); }\r
 \r
-       PBYTE data() const { return data_.get(); }\r
-       size_t size() const { return size_; }\r
-private:\r
-\r
-       static std::unique_ptr<tbb::mutex::scoped_lock> get_lock()\r
-       {\r
-               static tbb::mutex mutex;\r
-               return std::move(std::unique_ptr<tbb::mutex::scoped_lock>(new tbb::mutex::scoped_lock(mutex)));\r
-       }\r
-       \r
-       struct virtual_free\r
-       {\r
-               void operator()(LPVOID lpAddress)\r
-               {\r
-                       if(lpAddress != nullptr)                \r
-                               try{::VirtualFree(lpAddress, 0, MEM_RELEASE);}catch(...){}              \r
-               }\r
-       };\r
+       size_t image_size() const { return image_size_; }\r
+       size_t hanc_size() const { return hanc_size_; }\r
 \r
-       size_t size_;\r
-       std::unique_ptr<BYTE, virtual_free> data_;\r
+private:       \r
+       int id_;\r
+       size_t image_size_;\r
+       size_t hanc_size_;\r
+       std::vector<BYTE, page_locked_allocator<BYTE>> image_buffer_;   \r
+       std::vector<BYTE, page_locked_allocator<BYTE>> hanc_buffer_;\r
 };\r
-typedef std::shared_ptr<page_locked_buffer> page_locked_buffer_ptr;\r
+typedef std::shared_ptr<blue_dma_buffer> blue_dma_buffer_ptr;\r
 \r
 }}}
\ No newline at end of file
index 84716f5ac154cfb67b1a1f281fe061b60a9ddd4c..87716cce76117a80adf14ce34cfe3aa2bda41fc3 100644 (file)
@@ -147,7 +147,7 @@ public:
                                });\r
                        });\r
 \r
-                       if(frame_processor_->get_video_format_desc().mode == video_mode::upper && codec_context_->codec_id == CODEC_ID_DVVIDEO) // Move up one field            \r
+                       if(codec_context_->codec_id == CODEC_ID_DVVIDEO) // Move up one field frame_processor_->get_video_format_desc().mode == video_mode::upper &&     \r
                                write->translate(0.0f, 1.0/static_cast<double>(height_));\r
 \r
                        return write;\r
@@ -161,9 +161,6 @@ public:
                        avpicture_fill(reinterpret_cast<AVPicture*>(&av_frame), write->image_data().begin(), PIX_FMT_BGRA, width_, height_);\r
                 \r
                        sws_scale(sws_context_.get(), decoded_frame->data, decoded_frame->linesize, 0, height_, av_frame.data, av_frame.linesize);      \r
-                                               \r
-                       if(frame_processor_->get_video_format_desc().mode == video_mode::upper && codec_context_->codec_id == CODEC_ID_DVVIDEO) // Move up one field            \r
-                               write->translate(0.0f, 1.0/static_cast<double>(height_));\r
 \r
                        return write;\r
                }       \r