--- /dev/null
+#pragma once\r
+\r
+namespace caspar {\r
+\r
+template<typename T>\r
+typename T::value_type pop_front(T& container)\r
+{\r
+ auto item = std::move(container.front());\r
+ container.pop_front();\r
+ return std::move(item);\r
+}\r
+\r
+template<typename T>\r
+std::vector<T> split(const T& container, size_t size)\r
+{\r
+ std::vector<T> result;\r
+ const auto last = container.end() - container.size() % size; \r
+ for(auto it = container.begin(); it != last; it += size)\r
+ result.push_back(T(it, it + size));\r
+ result.push_back(T(last, container.end()));\r
+\r
+ return std::move(result);\r
+}\r
+\r
+}
\ No newline at end of file
\r
#include "audio_decoder.h"\r
\r
+#include <common/utility/algorithm.h>\r
+\r
#if defined(_MSC_VER)\r
#pragma warning (push)\r
#pragma warning (disable : 4244)\r
namespace caspar {\r
\r
struct audio_decoder::implementation : boost::noncopyable\r
-{\r
- typedef std::vector<short, tbb::cache_aligned_allocator<short>> buffer;\r
- \r
+{ \r
AVCodecContext* codec_context_;\r
\r
const core::video_format_desc format_desc_;\r
\r
- buffer current_chunk_;\r
+ std::vector<short> current_chunk_;\r
\r
public:\r
explicit implementation(AVCodecContext* codec_context, const core::video_format_desc& format_desc) \r
\r
current_chunk_.resize(s + written_bytes/2);\r
\r
- const auto last = current_chunk_.end() - current_chunk_.size() % format_desc_.audio_samples_per_frame;\r
- \r
- std::vector<std::vector<short>> chunks;\r
- for(auto it = current_chunk_.begin(); it != last; it += format_desc_.audio_samples_per_frame) \r
- chunks.push_back(std::vector<short>(it, it + format_desc_.audio_samples_per_frame)); \r
+ auto chunks = split(current_chunk_, format_desc_.audio_samples_per_frame);\r
\r
- current_chunk_.erase(current_chunk_.begin(), last);\r
+ current_chunk_ = chunks.back();\r
+ chunks.pop_back();\r
\r
return chunks;\r
}\r
#include "audio/audio_decoder.h"\r
#include "video/video_decoder.h"\r
\r
-#include <common/utility/timer.h>\r
#include <common/diagnostics/graph.h>\r
+#include <common/env.h>\r
+#include <common/utility/algorithm.h>\r
\r
+#include <core/video_format.h>\r
#include <core/producer/frame/basic_frame.h>\r
#include <core/producer/frame/write_frame.h>\r
#include <core/producer/frame/audio_transform.h>\r
-#include <core/video_format.h>\r
-\r
-#include <common/env.h>\r
-#include <common/utility/timer.h>\r
-#include <common/utility/assert.h>\r
\r
#include <tbb/parallel_invoke.h>\r
\r
#include <boost/timer.hpp>\r
\r
#include <deque>\r
-#include <functional>\r
\r
namespace caspar {\r
\r
struct ffmpeg_producer : public core::frame_producer\r
{\r
- const std::wstring filename_;\r
- const bool loop_;\r
+ const std::wstring filename_;\r
+ const bool loop_;\r
\r
- std::shared_ptr<diagnostics::graph> graph_;\r
- boost::timer perf_timer_;\r
+ std::shared_ptr<diagnostics::graph> graph_;\r
+ boost::timer perf_timer_;\r
\r
std::deque<safe_ptr<core::write_frame>> video_frame_buffer_; \r
std::deque<std::vector<short>> audio_chunk_buffer_;\r
-\r
- std::queue<safe_ptr<core::basic_frame>> ouput_channel_;\r
+ std::queue<safe_ptr<core::basic_frame>> output_channel_;\r
\r
std::shared_ptr<core::frame_factory> frame_factory_;\r
\r
- input input_; \r
- std::unique_ptr<video_decoder> video_decoder_;\r
- std::unique_ptr<audio_decoder> audio_decoder_;\r
+ input input_; \r
+ std::unique_ptr<video_decoder> video_decoder_;\r
+ std::unique_ptr<audio_decoder> audio_decoder_;\r
public:\r
explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, bool loop, int start_frame, int end_frame) \r
: filename_(filename)\r
{\r
perf_timer_.restart();\r
\r
- for(size_t n = 0; ouput_channel_.size() < 2 && input_.has_packet() && n < 32; ++n) // 32 packets should be enough. Otherwise there probably was an error and we want to avoid infinite recursion.\r
+ for(size_t n = 0; output_channel_.size() < 2 && input_.has_packet() && n < 32; ++n) // 32 packets should be enough. Otherwise there probably was an error and we want to avoid infinite recursion.\r
{ \r
tbb::parallel_invoke\r
(\r
\r
if(!video_frame_buffer_.empty() && !audio_chunk_buffer_.empty())\r
{\r
- frame = video_frame_buffer_.front(); \r
- video_frame_buffer_.pop_front();\r
- \r
- frame->audio_data() = std::move(audio_chunk_buffer_.front());\r
- audio_chunk_buffer_.pop_front(); \r
+ frame = pop_front(video_frame_buffer_);\r
+ frame->audio_data() = pop_front(audio_chunk_buffer_);\r
}\r
else if(!video_frame_buffer_.empty() && !audio_decoder_)\r
{\r
- frame = video_frame_buffer_.front(); \r
- video_frame_buffer_.pop_front();\r
+ frame = pop_front(video_frame_buffer_);\r
frame->get_audio_transform().set_has_audio(false); \r
}\r
else if(!audio_chunk_buffer_.empty() && !video_decoder_)\r
frame = frame_factory_->create_frame(this, 1, 1);\r
std::fill(frame->image_data().begin(), frame->image_data().end(), 0);\r
\r
- frame->audio_data() = std::move(audio_chunk_buffer_.front());\r
- audio_chunk_buffer_.pop_front();\r
+ frame->audio_data() = pop_front(audio_chunk_buffer_);\r
}\r
\r
if(frame)\r
- ouput_channel_.push(make_safe(frame)); \r
+ output_channel_.push(make_safe(frame)); \r
}\r
\r
safe_ptr<core::basic_frame> get_next_frame()\r
if(is_eof())\r
return core::basic_frame::eof();\r
\r
- if(ouput_channel_.empty())\r
+ if(output_channel_.empty())\r
{\r
graph_->add_tag("underflow");\r
return core::basic_frame::late(); \r
}\r
\r
- auto frame = std::move(ouput_channel_.front());\r
- ouput_channel_.pop(); \r
- return frame;\r
+ return pop_front(output_channel_);\r
}\r
\r
bool is_eof() const\r
{\r
- return ouput_channel_.empty() && (!video_decoder_ && !audio_decoder_) || !input_.is_running();\r
+ return output_channel_.empty() && (!video_decoder_ && !audio_decoder_) || !input_.is_running();\r
}\r
};\r
\r