\r
namespace caspar { namespace ffmpeg {\r
\r
-struct frame_muxer2::implementation : public Concurrency::agent, boost::noncopyable\r
+struct frame_muxer2::implementation : boost::noncopyable\r
{ \r
- typedef std::pair<safe_ptr<core::write_frame>, ticket_t> write_element_t;\r
+ typedef std::pair<std::shared_ptr<AVFrame>, ticket_t> video_element_t;\r
typedef std::pair<safe_ptr<core::audio_buffer>, ticket_t> audio_element_t;\r
\r
frame_muxer2::video_source_t* video_source_;\r
frame_muxer2::audio_source_t* audio_source_;\r
\r
- ITarget<frame_muxer2::target_element_t>& target_;\r
mutable single_assignment<display_mode::type> display_mode_;\r
const double in_fps_;\r
const core::video_format_desc format_desc_;\r
\r
core::audio_buffer audio_data_;\r
\r
- std::queue<write_element_t> video_frames_;\r
+ std::queue<video_element_t> video_frames_;\r
std::queue<audio_element_t> audio_buffers_;\r
\r
std::wstring filter_str_;\r
\r
implementation(frame_muxer2::video_source_t* video_source,\r
frame_muxer2::audio_source_t* audio_source,\r
- frame_muxer2::target_t& target,\r
double in_fps, \r
const safe_ptr<core::frame_factory>& frame_factory,\r
const std::wstring& filter)\r
: video_source_(video_source)\r
, audio_source_(audio_source)\r
- , target_(target)\r
, in_fps_(in_fps)\r
, format_desc_(frame_factory->get_video_format_desc())\r
, auto_transcode_(env::properties().get("configuration.producers.auto-transcode", false))\r
, frame_factory_(frame_factory)\r
, eof_(false)\r
{ \r
- start();\r
}\r
-\r
- ~implementation()\r
- {\r
- agent::wait(this);\r
- }\r
- \r
+ \r
safe_ptr<core::write_frame> receive_video(ticket_t& tickets)\r
{ \r
if(!video_source_)\r
auto video_frame = std::move(video_frames_.front());\r
video_frames_.pop();\r
boost::range::push_back(tickets, video_frame.second);\r
- return video_frame.first;\r
+ return make_write_frame(this, make_safe_ptr(video_frame.first), frame_factory_, 0);\r
}\r
\r
- auto element = receive(video_source_);\r
+ auto element = Concurrency::receive(video_source_);\r
auto video = element.first;\r
\r
if(video == loop_video())\r
initialize_display_mode(*video);\r
\r
filter_.value()->push(video);\r
- for(auto frame = filter_.value()->poll(); frame; frame = filter_.value()->poll()) \r
- video_frames_.push(write_element_t(make_write_frame(this, make_safe_ptr(frame), frame_factory_, 0), element.second)); \r
- \r
+ for(auto frame = filter_.value()->poll(); frame; frame = filter_.value()->poll()) \r
+ {\r
+ video_frames_.push(video_element_t(make_safe_ptr(frame), element.second)); \r
+ if(display_mode_.value() == display_mode::duplicate)\r
+ video_frames_.push(video_element_t(make_safe_ptr(frame), element.second)); \r
+ }\r
+\r
return receive_video(tickets);\r
}\r
\r
return audio_buffer.first;\r
}\r
\r
- auto element = receive(audio_source_);\r
+ auto element = Concurrency::receive(audio_source_);\r
auto audio = element.first;\r
\r
if(audio == loop_audio())\r
\r
return receive_audio(tickets);\r
}\r
- \r
- virtual void run()\r
+ \r
+ \r
+ safe_ptr<core::basic_frame> receive_frame()\r
{\r
try\r
{\r
- while(!eof_)\r
- {\r
- ticket_t tickets;\r
+ if(eof_)\r
+ return core::basic_frame::eof();\r
+\r
+ ticket_t tickets;\r
\r
- auto video = receive_video(tickets);\r
- video->audio_data() = std::move(*receive_audio(tickets));\r
+ auto video = receive_video(tickets);\r
+ video->audio_data() = std::move(*receive_audio(tickets));\r
\r
- if(eof_)\r
- break;\r
+ if(eof_)\r
+ return core::basic_frame::eof();\r
\r
- switch(display_mode_.value())\r
+ switch(display_mode_.value())\r
+ {\r
+ case display_mode::simple: \r
+ case display_mode::deinterlace:\r
+ case display_mode::deinterlace_bob:\r
+ case display_mode::duplicate:\r
{\r
- case display_mode::simple: \r
- case display_mode::deinterlace:\r
- case display_mode::deinterlace_bob:\r
- {\r
- send(target_, frame_muxer2::target_element_t(std::move(video), std::move(tickets)));\r
-\r
- break;\r
- }\r
- case display_mode::duplicate: \r
- { \r
- auto video2 = make_safe<core::write_frame>(*video); \r
- video2->audio_data() = std::move(*receive_audio(tickets));\r
-\r
- send(target_, frame_muxer2::target_element_t(std::move(video), std::move(tickets))); \r
- send(target_, frame_muxer2::target_element_t(std::move(video2), std::move(tickets)));\r
-\r
- break;\r
- }\r
- case display_mode::half: \r
- { \r
- send(target_, frame_muxer2::target_element_t(std::move(video), std::move(tickets)));\r
- receive_video(tickets);\r
-\r
- break;\r
- }\r
- case display_mode::deinterlace_bob_reinterlace:\r
- case display_mode::interlace: \r
- { \r
- auto video2 = receive_video(tickets);\r
- \r
- auto frame = core::basic_frame::interlace(std::move(video), std::move(video2), format_desc_.field_mode); \r
- send(target_, frame_muxer2::target_element_t(std::move(frame), std::move(tickets)));\r
-\r
- break;\r
- }\r
- default: \r
- BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("invalid display-mode"));\r
+ return video;\r
+ } \r
+ case display_mode::half: \r
+ { \r
+ receive_video(tickets); \r
+ return video;\r
}\r
- } \r
+ case display_mode::deinterlace_bob_reinterlace:\r
+ case display_mode::interlace: \r
+ { \r
+ auto video2 = receive_video(tickets); \r
+ return core::basic_frame::interlace(std::move(video), std::move(video2), format_desc_.field_mode); \r
+ }\r
+ default: \r
+ BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("invalid display-mode"));\r
+ }\r
}\r
catch(...)\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
+ eof_ = true;\r
+ return core::basic_frame::eof();\r
}\r
- \r
- send(target_, frame_muxer2::target_element_t(core::basic_frame::eof(), ticket_t()));\r
-\r
- done();\r
}\r
\r
void initialize_display_mode(AVFrame& frame)\r
\r
frame_muxer2::frame_muxer2(video_source_t* video_source, \r
audio_source_t* audio_source,\r
- target_t& target,\r
double in_fps, \r
const safe_ptr<core::frame_factory>& frame_factory,\r
const std::wstring& filter)\r
- : impl_(new implementation(video_source, audio_source, target, in_fps, frame_factory, filter))\r
+ : impl_(new implementation(video_source, audio_source, in_fps, frame_factory, filter))\r
{\r
}\r
\r
return impl_->calc_nb_frames(nb_frames);\r
}\r
\r
+safe_ptr<core::basic_frame> frame_muxer2::receive()\r
+{\r
+ return impl_->receive_frame();\r
+}\r
+\r
}}
\ No newline at end of file