std::deque<std::pair<int, std::vector<short>>> audio_chunks_;\r
std::deque<std::pair<int, safe_ptr<core::write_frame>>> video_frames_;\r
public:\r
- explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::string& filter, bool loop, int start, int length) \r
+ explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, bool loop, int start, int length) \r
: filename_(filename)\r
, graph_(diagnostics::create_graph(narrow(print())))\r
, frame_factory_(frame_factory) \r
CASPAR_LOG(warning) << print() << L" Invalid framerate detected. This may cause distorted audio during playback. frame-time: " << frame_time;\r
\r
video_decoder_.reset(input_.get_video_codec_context() ? \r
- new video_decoder(input_, frame_factory, filter) : nullptr);\r
+ new video_decoder(input_, frame_factory) : nullptr);\r
\r
audio_decoder_.reset(input_.get_audio_codec_context() ? \r
new audio_decoder(input_, frame_factory->get_video_format_desc()) : nullptr); \r
(\r
[&]\r
{\r
- if(video_decoder_ && video_frames_.size() < 3)\r
+ if(video_decoder_ && video_frames_.size() < 2)\r
boost::range::push_back(video_frames_, video_decoder_->receive()); \r
}, \r
[&]\r
{\r
- if(audio_decoder_ && audio_chunks_.size() < 3)\r
+ if(audio_decoder_ && audio_chunks_.size() < 2)\r
boost::range::push_back(audio_chunks_, audio_decoder_->receive()); \r
}\r
);\r
CASPAR_ASSERT(!(video_decoder_ && audio_decoder_ && !video_frames_.empty() && !audio_chunks_.empty()) ||\r
video_frames_.front().first == audio_chunks_.front().first);\r
}\r
- \r
+\r
safe_ptr<core::basic_frame> decode_frame()\r
{\r
decode_packets();\r
\r
if(video_decoder_ && audio_decoder_ && !video_frames_.empty() && !audio_chunks_.empty())\r
{\r
- auto frame = std::move(video_frames_.front().second); \r
- auto frame_number = video_frames_.front().first;\r
+ auto frame = std::move(video_frames_.front().second); \r
video_frames_.pop_front();\r
\r
frame->audio_data() = std::move(audio_chunks_.front().second);\r
audio_chunks_.pop_front();\r
\r
- if(!video_frames_.empty())\r
- {\r
- if(video_frames_.front().first == frame_number)\r
- {\r
- auto frame2 = video_frames_.front().second;\r
- video_frames_.pop_front();\r
-\r
- return core::basic_frame::interlace(frame, frame2, frame_factory_->get_video_format_desc().mode);\r
- }\r
- }\r
-\r
return frame;\r
}\r
else if(video_decoder_ && !audio_decoder_ && !video_frames_.empty())\r
{\r
- auto frame = std::move(video_frames_.front().second); \r
- auto frame_number = video_frames_.front().first;\r
+ auto frame = std::move(video_frames_.front().second); \r
video_frames_.pop_front();\r
-\r
frame->get_audio_transform().set_has_audio(false); \r
\r
- if(!video_frames_.empty())\r
- {\r
- if(video_frames_.front().first == frame_number)\r
- {\r
- auto frame2 = video_frames_.front().second;\r
- video_frames_.pop_front();\r
-\r
- return core::basic_frame::interlace(frame, frame2, frame_factory_->get_video_format_desc().mode);\r
- }\r
- }\r
-\r
return frame;\r
}\r
else if(audio_decoder_ && !video_decoder_ && !audio_chunks_.empty())\r
start = boost::lexical_cast<int>(*seek_it);\r
}\r
\r
- std::string filter;\r
-\r
- auto filter_it = std::find(params.begin(), params.end(), L"FILTER");\r
- if(filter_it != params.end())\r
- {\r
- if(++filter_it != params.end())\r
- filter = narrow(*filter_it);\r
- std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower);\r
- }\r
-\r
- return make_safe<ffmpeg_producer>(frame_factory, path, filter, loop, start, length);\r
+ return make_safe<ffmpeg_producer>(frame_factory, path, loop, start, length);\r
}\r
\r
}
\ No newline at end of file
\r
#include "video_decoder.h"\r
#include "../../ffmpeg_error.h"\r
-#include "../../util/util.h"\r
-#include "../../util/filter.h"\r
\r
#include <common/memory/memcpy.h>\r
\r
\r
namespace caspar {\r
\r
+core::pixel_format::type get_pixel_format(PixelFormat pix_fmt)\r
+{\r
+ switch(pix_fmt)\r
+ {\r
+ case PIX_FMT_GRAY8: return core::pixel_format::gray;\r
+ case PIX_FMT_BGRA: return core::pixel_format::bgra;\r
+ case PIX_FMT_ARGB: return core::pixel_format::argb;\r
+ case PIX_FMT_RGBA: return core::pixel_format::rgba;\r
+ case PIX_FMT_ABGR: return core::pixel_format::abgr;\r
+ case PIX_FMT_YUV444P: return core::pixel_format::ycbcr;\r
+ case PIX_FMT_YUV422P: return core::pixel_format::ycbcr;\r
+ case PIX_FMT_YUV420P: return core::pixel_format::ycbcr;\r
+ case PIX_FMT_YUV411P: return core::pixel_format::ycbcr;\r
+ case PIX_FMT_YUV410P: return core::pixel_format::ycbcr;\r
+ case PIX_FMT_YUVA420P: return core::pixel_format::ycbcra;\r
+ default: return core::pixel_format::invalid;\r
+ }\r
+}\r
+\r
+core::pixel_format_desc get_pixel_format_desc(PixelFormat pix_fmt, size_t width, size_t height)\r
+{\r
+ // Get linesizes\r
+ AVPicture dummy_pict; \r
+ avpicture_fill(&dummy_pict, nullptr, pix_fmt, width, height);\r
+\r
+ core::pixel_format_desc desc;\r
+ desc.pix_fmt = get_pixel_format(pix_fmt);\r
+ \r
+ switch(desc.pix_fmt)\r
+ {\r
+ case core::pixel_format::gray:\r
+ {\r
+ desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[0]/4, height, 1)); \r
+ return desc;\r
+ }\r
+ case core::pixel_format::bgra:\r
+ case core::pixel_format::argb:\r
+ case core::pixel_format::rgba:\r
+ case core::pixel_format::abgr:\r
+ {\r
+ desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[0]/4, height, 4)); \r
+ return desc;\r
+ }\r
+ case core::pixel_format::ycbcr:\r
+ case core::pixel_format::ycbcra:\r
+ { \r
+ // Find chroma height\r
+ size_t size2 = dummy_pict.data[2] - dummy_pict.data[1];\r
+ size_t h2 = size2/dummy_pict.linesize[1]; \r
+\r
+ desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[0], height, 1));\r
+ desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[1], h2, 1));\r
+ desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[2], h2, 1));\r
+\r
+ if(desc.pix_fmt == core::pixel_format::ycbcra) \r
+ desc.planes.push_back(core::pixel_format_desc::plane(dummy_pict.linesize[3], height, 1)); \r
+ return desc;\r
+ } \r
+ default: \r
+ desc.pix_fmt = core::pixel_format::invalid;\r
+ return desc;\r
+ }\r
+}\r
+\r
struct video_decoder::implementation : boost::noncopyable\r
{\r
input& input_;\r
std::shared_ptr<SwsContext> sws_context_;\r
- const safe_ptr<core::frame_factory> frame_factory_;\r
+ const std::shared_ptr<core::frame_factory> frame_factory_;\r
AVCodecContext& codec_context_;\r
const int width_;\r
const int height_;\r
const PixelFormat pix_fmt_;\r
core::pixel_format_desc desc_;\r
size_t frame_number_;\r
- std::shared_ptr<filter> filter_;\r
\r
public:\r
- explicit implementation(input& input, const safe_ptr<core::frame_factory>& frame_factory, const std::string& filter_str) \r
+ explicit implementation(input& input, const safe_ptr<core::frame_factory>& frame_factory) \r
: input_(input)\r
, frame_factory_(frame_factory)\r
, codec_context_(*input_.get_video_codec_context())\r
msg_info("Could not create software scaling context.") << \r
boost::errinfo_api_function("sws_getContext"));\r
}\r
-\r
- if(!filter_str.empty())\r
- filter_.reset(new filter(filter_str));\r
}\r
\r
std::deque<std::pair<int, safe_ptr<core::write_frame>>> receive()\r
}\r
\r
if(frame_finished != 0) \r
- {\r
- if(filter_)\r
- {\r
- filter_->push(decoded_frame);\r
-\r
- std::shared_ptr<AVFrame> frame;\r
- while(filter_->try_pop(frame))\r
- result.push_back(std::make_pair(frame_number_, make_write_frame(make_safe(frame))));\r
- }\r
- else\r
- result.push_back(std::make_pair(frame_number_, make_write_frame(decoded_frame)));\r
- \r
- if(!result.empty())\r
- ++frame_number_;\r
- else\r
- CASPAR_LOG(trace) << " Filter delay.";\r
- }\r
- else\r
- CASPAR_LOG(trace) << " Decoder delay.";\r
+ result.push_back(std::make_pair(frame_number_++, make_write_frame(decoded_frame)));\r
\r
return result;\r
}\r
}\r
};\r
\r
-video_decoder::video_decoder(input& input, const safe_ptr<core::frame_factory>& frame_factory, const std::string& filter) : impl_(new implementation(input, frame_factory, filter)){}\r
+video_decoder::video_decoder(input& input, const safe_ptr<core::frame_factory>& frame_factory) : impl_(new implementation(input, frame_factory)){}\r
std::deque<std::pair<int, safe_ptr<core::write_frame>>> video_decoder::receive(){return impl_->receive();}\r
\r
}
\ No newline at end of file