\r
#include <gl/glew.h>\r
\r
+#include <tbb/atomic.h>\r
+\r
namespace caspar { namespace core {\r
\r
static GLenum FORMAT[] = {0, GL_RED, GL_RG, GL_BGR, GL_BGRA};\r
return FORMAT[stride];\r
}\r
\r
+static tbb::atomic<int> g_total_count;\r
+\r
struct device_buffer::implementation : boost::noncopyable\r
{\r
GLuint id_;\r
GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
GL(glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT[stride_], width_, height_, 0, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
GL(glBindTexture(GL_TEXTURE_2D, 0));\r
- CASPAR_LOG(debug) << "[device_buffer] allocated size:" << width*height*stride; \r
+ CASPAR_LOG(debug) << "[device_buffer] [" << ++g_total_count << L"] allocated size:" << width*height*stride; \r
} \r
\r
~implementation()\r
try\r
{\r
GL(glDeleteTextures(1, &id_));\r
+ CASPAR_LOG(debug) << "[device_buffer] [" << --g_total_count << L"] deallocated size:" << width_*height_*stride_;\r
}\r
catch(...)\r
{\r
\r
#include <gl/glew.h>\r
\r
+#include <tbb/atomic.h>\r
+\r
namespace caspar { namespace core {\r
+\r
+static tbb::atomic<int> g_w_total_count;\r
+static tbb::atomic<int> g_r_total_count;\r
\r
struct host_buffer::implementation : boost::noncopyable\r
{ \r
if(!pbo_)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
\r
- CASPAR_LOG(debug) << "[host_buffer] allocated size:" << size_ << " usage: " << (usage == write_only ? "write_only" : "read_only");\r
+ CASPAR_LOG(debug) << "[host_buffer] [" << ++(usage_ == write_only ? g_w_total_count : g_r_total_count) << L"] allocated size:" << size_ << " usage: " << (usage == write_only ? "write_only" : "read_only");\r
} \r
\r
~implementation()\r
try\r
{\r
GL(glDeleteBuffers(1, &pbo_));\r
+ CASPAR_LOG(debug) << "[host_buffer] [" << --(usage_ == write_only ? g_w_total_count : g_r_total_count) << L"] deallocated size:" << size_ << " usage: " << (usage_ == write_only ? "write_only" : "read_only");\r
}\r
catch(...)\r
{\r
GL(glGenFramebuffers(1, &fbo_)); \r
GL(glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_));\r
GL(glReadBuffer(GL_COLOR_ATTACHMENT0_EXT));\r
+ GL(glDisable(GL_MULTISAMPLE_ARB));\r
});\r
}\r
\r
\r
safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer, int hints)\r
{ \r
- if(producer == frame_producer::empty())\r
- return basic_frame::eof();\r
-\r
auto frame = producer->receive(hints);\r
if(frame == basic_frame::eof())\r
{\r
auto following = producer->get_following_producer();\r
following->set_leading_producer(producer);\r
producer = std::move(following); \r
- \r
+ \r
+ if(producer == frame_producer::empty())\r
+ return basic_frame::eof();\r
+\r
return receive_and_follow(producer, hints);\r
}\r
return frame;\r
bool is_paused_;\r
int auto_play_delta_;\r
int64_t frame_number_;\r
+ safe_ptr<core::basic_frame> last_frame_;\r
+\r
public:\r
implementation() \r
: foreground_(frame_producer::empty())\r
, background_(frame_producer::empty())\r
, is_paused_(false)\r
, auto_play_delta_(-1)\r
- , frame_number_(0){}\r
+ , frame_number_(0)\r
+ , last_frame_(core::basic_frame::empty()){}\r
\r
void pause()\r
{\r
{\r
foreground_ = frame_producer::empty();\r
frame_number_ = 0;\r
+ last_frame_ = core::basic_frame::empty();\r
}\r
\r
safe_ptr<basic_frame> receive()\r
try\r
{\r
if(is_paused_)\r
- return foreground_->last_frame();\r
+ return disable_audio(last_frame_);\r
\r
const auto frames_left = foreground_->nb_frames() - (++frame_number_) - auto_play_delta_;\r
\r
\r
if(auto_play_delta_ >= 0)\r
{\r
+ CASPAR_ASSERT(background_ != core::frame_producer::empty());\r
if(frames_left <= 0 || frame == core::basic_frame::eof())\r
{\r
//CASPAR_ASSERT(frame != core::basic_frame::eof() && "Received early EOF. Media duration metadata incorrect.");\r
frame = receive();\r
}\r
}\r
+\r
+ if(frame == core::basic_frame::eof())\r
+ {\r
+ pause();\r
+ return receive();\r
+ }\r
\r
- return frame;\r
+ return last_frame_ = frame;\r
}\r
catch(...)\r
{\r
\r
virtual safe_ptr<core::basic_frame> last_frame() const\r
{\r
- return last_frame_;\r
+ return disable_audio(last_frame_);\r
}\r
\r
virtual std::wstring print() const\r
\r
virtual safe_ptr<core::basic_frame> last_frame() const\r
{\r
- return last_frame_;\r
+ return disable_audio(last_frame_);\r
}\r
\r
virtual int64_t nb_frames() const \r
const bool loop_;\r
\r
safe_ptr<core::basic_frame> last_frame_;\r
- bool eof_;\r
\r
public:\r
explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, int start, int length) \r
, start_(start)\r
, loop_(loop)\r
, last_frame_(core::basic_frame::empty())\r
- , eof_(false)\r
{\r
graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
\r
virtual safe_ptr<core::basic_frame> receive(int hints)\r
{\r
- if(eof_)\r
- return last_frame();\r
-\r
auto frame = core::basic_frame::late();\r
\r
frame_timer_.restart();\r
else\r
{\r
if(input_.eof())\r
- {\r
- eof_ = true;\r
- return last_frame();\r
- }\r
+ return core::basic_frame::eof();\r
else\r
{\r
graph_->add_tag("underflow"); \r