std::wstring filter_str_;\r
\r
governor governor_;\r
- tbb::atomic<bool> is_running_;\r
\r
implementation(frame_muxer2::video_source_t* video_source,\r
frame_muxer2::audio_source_t* audio_source,\r
, frame_factory_(frame_factory)\r
, governor_(2)\r
{ \r
- is_running_ = true;\r
start();\r
}\r
\r
\r
video = receive(video_source_);\r
\r
- if(video == loop_video())\r
+ if(video == flush_video())\r
+ {\r
+ if(filter_.has_value())\r
+ filter_.value()->push(nullptr);\r
return receive_video();\r
+ }\r
\r
if(video == eof_video())\r
- {\r
- is_running_ = false;\r
- return nullptr;\r
- }\r
+ return nullptr; \r
\r
if(!display_mode_.has_value())\r
initialize_display_mode(*video);\r
\r
- filter_.value()->push(std::move(video));\r
+ filter_.value()->push(video);\r
+ video.reset();\r
\r
return receive_video();\r
}\r
\r
- std::shared_ptr<core::audio_buffer> receive_audio()\r
+ std::shared_ptr<core::audio_buffer> receive_audio(size_t n_samples)\r
{ \r
if(!audio_source_)\r
- return make_safe<core::audio_buffer>(format_desc_.audio_samples_per_frame, 0);\r
+ return make_safe<core::audio_buffer>(n_samples, 0);\r
\r
- if(audio_data_.size() >= format_desc_.audio_samples_per_frame)\r
+ if(audio_data_.size() >= n_samples)\r
{\r
auto begin = audio_data_.begin(); \r
- auto end = begin + format_desc_.audio_samples_per_frame;\r
+ auto end = begin + n_samples;\r
auto audio = make_safe<core::audio_buffer>(begin, end);\r
audio_data_.erase(begin, end);\r
return audio;\r
}\r
\r
- auto audio = receive(audio_source_);\r
+ std::shared_ptr<core::audio_buffer> audio = receive(audio_source_);\r
\r
- if(audio == loop_audio())\r
+ if(audio == flush_audio())\r
{\r
if(!audio_data_.empty())\r
{\r
}\r
\r
if(audio == eof_audio())\r
- {\r
- is_running_ = false;\r
return nullptr;\r
- }\r
\r
audio_data_.insert(audio_data_.end(), audio->begin(), audio->end()); \r
-\r
- return receive_audio();\r
+ audio.reset();\r
+ \r
+ return receive_audio(n_samples);\r
}\r
\r
virtual void run()\r
try\r
{\r
win32_exception::install_handler();\r
- while(is_running_)\r
+ while(display())\r
{ \r
- auto ticket = governor_.acquire();\r
-\r
- auto video = receive_video();\r
- if(!video)\r
- break;\r
-\r
- auto audio = receive_audio();\r
-\r
- if(!audio)\r
- break;\r
-\r
- video->audio_data() = std::move(*audio);\r
+ }\r
\r
- switch(display_mode_.value())\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(video, ticket));\r
-\r
- break;\r
- }\r
- case display_mode::duplicate: \r
- { \r
- auto video2 = make_safe<core::write_frame>(*video); \r
- auto audio2 = receive_audio();\r
- \r
- send(target_, frame_muxer2::target_element_t(video, ticket));\r
- if(audio2)\r
- {\r
- video2->audio_data() = std::move(*receive_audio()); \r
- send(target_, frame_muxer2::target_element_t(video2, ticket));\r
- }\r
-\r
- break;\r
- }\r
- case display_mode::half: \r
- { \r
- send(target_, frame_muxer2::target_element_t(video, ticket));\r
- receive_video();\r
-\r
- break;\r
- }\r
- case display_mode::deinterlace_bob_reinterlace:\r
- case display_mode::interlace: \r
- { \r
- std::shared_ptr<core::basic_frame> video2 = receive_video();\r
- if(!video2)\r
- video2 = core::basic_frame::empty();\r
- \r
- auto frame = core::basic_frame::interlace(make_safe_ptr(video), make_safe_ptr(video2), format_desc_.field_mode); \r
- send(target_, frame_muxer2::target_element_t(frame, ticket));\r
-\r
- break;\r
- }\r
- default: \r
- BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("invalid display-mode"));\r
- }\r
- } \r
}\r
catch(...)\r
{\r
done();\r
}\r
\r
+ bool display()\r
+ {\r
+ auto ticket = governor_.acquire();\r
+\r
+ auto video = receive_video();\r
+ if(!video)\r
+ return false;\r
+\r
+ auto audio = receive_audio(format_desc_.audio_samples_per_frame);\r
+ if(!audio)\r
+ return false;\r
+ \r
+ video->audio_data() = std::move(*audio);\r
+\r
+ switch(display_mode_.value())\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(video, ticket));\r
+ \r
+ return true;\r
+ }\r
+ case display_mode::duplicate: \r
+ { \r
+ send(target_, frame_muxer2::target_element_t(video, ticket));\r
+ \r
+ auto video2 = make_safe<core::write_frame>(*video); \r
+ auto audio2 = receive_audio(format_desc_.audio_samples_per_frame);\r
+\r
+ if(audio2)\r
+ {\r
+ video2->audio_data() = std::move(*audio2);\r
+ send(target_, frame_muxer2::target_element_t(video2, ticket));\r
+ }\r
+\r
+ return audio2 != nullptr;\r
+ }\r
+ case display_mode::half: \r
+ { \r
+ send(target_, frame_muxer2::target_element_t(video, ticket));\r
+ auto video2 = receive_video();\r
+ \r
+ return video2 != nullptr;\r
+ }\r
+ case display_mode::deinterlace_bob_reinterlace:\r
+ case display_mode::interlace: \r
+ { \r
+ std::shared_ptr<core::basic_frame> video2 = receive_video();\r
+ if(!video2)\r
+ video2 = core::basic_frame::empty();\r
+ \r
+ auto frame = core::basic_frame::interlace(make_safe_ptr(video), make_safe_ptr(video2), format_desc_.field_mode); \r
+ send(target_, frame_muxer2::target_element_t(frame, ticket));\r
+ \r
+ return video2 != nullptr;\r
+ }\r
+ default: \r
+ BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("invalid display-mode"));\r
+ }\r
+ } \r
+ \r
void initialize_display_mode(AVFrame& frame)\r
{\r
auto display_mode = display_mode::invalid;\r