, device_index_(device_index)\r
, frame_factory_(frame_factory)\r
, filter_(filter)\r
- , muxer_(double_rate(filter) ? format_desc.fps * 2.0 : format_desc.fps, frame_factory->get_video_format_desc(), frame_factory)\r
+ , muxer_(double_rate(filter) ? format_desc.fps * 2.0 : format_desc.fps, frame_factory)\r
{\r
frame_buffer_.set_capacity(2);\r
\r
\r
#include "audio_decoder.h"\r
\r
+#include "../../ffmpeg_error.h"\r
+\r
#include <tbb/task_group.h>\r
\r
#if defined(_MSC_VER)\r
explicit implementation(const std::shared_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc) \r
: format_desc_(format_desc) \r
, nb_frames_(0)\r
- { \r
- AVCodec* dec;\r
- index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);\r
+ { \r
+ try\r
+ {\r
+ AVCodec* dec;\r
+ index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);\r
\r
- if(index_ < 0)\r
- return;\r
+ if(index_ < 0)\r
+ {\r
+ BOOST_THROW_EXCEPTION(\r
+ file_read_error() <<\r
+ msg_info(av_error_str(index_)) <<\r
+ boost::errinfo_api_function("av_find_best_stream") <<\r
+ boost::errinfo_errno(AVUNERROR(index_)));\r
+ }\r
\r
- int errn = avcodec_open(context->streams[index_]->codec, dec);\r
- if(errn < 0)\r
+ const int ret = avcodec_open(context->streams[index_]->codec, dec);\r
+ if(ret < 0)\r
+ { \r
+ BOOST_THROW_EXCEPTION(\r
+ file_read_error() <<\r
+ msg_info(av_error_str(ret)) <<\r
+ boost::errinfo_api_function("avcodec_open") <<\r
+ boost::errinfo_errno(AVUNERROR(ret)));\r
+ }\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ CASPAR_LOG(warning) << "[audio_decoder] Failed to open audio. Running without audio.";\r
return;\r
- \r
+ }\r
+\r
codec_context_.reset(context->streams[index_]->codec, avcodec_close);\r
\r
//nb_frames_ = context->streams[index_]->nb_frames;\r
{ \r
BOOST_THROW_EXCEPTION(\r
invalid_operation() <<\r
+ msg_info(av_error_str(ret)) <<\r
boost::errinfo_api_function("avcodec_decode_audio2") <<\r
boost::errinfo_errno(AVUNERROR(ret)));\r
}\r
, input_(graph_, filename_, loop, start, length)\r
, video_decoder_(input_.context(), frame_factory, filter)\r
, audio_decoder_(input_.context(), frame_factory->get_video_format_desc())\r
- , muxer_(video_decoder_.fps(), format_desc_, frame_factory)\r
+ , muxer_(video_decoder_.fps(), frame_factory)\r
, start_(start)\r
, nb_frames_(video_decoder_.nb_frames() - start)\r
, loop_(loop)\r
class filter\r
{\r
public:\r
- filter(const std::wstring& filters);\r
+ filter(const std::wstring& filters = L"");\r
\r
std::vector<safe_ptr<AVFrame>> execute(const std::shared_ptr<AVFrame>& frame);\r
\r
size_t processed_audio_sample_count_;\r
size_t processed_video_frame_count_;\r
\r
- std::unique_ptr<filter> filter_;\r
+ filter filter_;\r
safe_ptr<core::frame_factory> frame_factory_;\r
\r
- implementation(double in_fps, const video_format_desc& format_desc, const safe_ptr<core::frame_factory>& frame_factory)\r
- : display_mode_(display_mode::invalid)\r
+ implementation(double in_fps, const safe_ptr<core::frame_factory>& frame_factory)\r
+ : video_streams_(1)\r
+ , audio_streams_(1)\r
+ , display_mode_(display_mode::invalid)\r
, in_fps_(in_fps)\r
- , format_desc_(format_desc)\r
+ , format_desc_(frame_factory->get_video_format_desc())\r
, auto_mode_(env::properties().get("configuration.auto-mode", false))\r
, audio_sample_count_(0)\r
, video_frame_count_(0)\r
, frame_factory_(frame_factory)\r
- , video_streams_(1)\r
- , audio_streams_(1)\r
{\r
}\r
\r
{\r
video_streams_.back().push(make_safe<core::write_frame>(this));\r
++video_frame_count_;\r
- process(frame_buffer_);\r
+ put_frames(frame_buffer_);\r
return;\r
}\r
\r
if(display_mode_ == display_mode::invalid)\r
{\r
- auto in_mode = get_mode(*video_frame);\r
- display_mode_ = auto_mode_ ? get_display_mode(in_mode, in_fps_, format_desc_.mode, format_desc_.fps) : display_mode::simple;\r
+ if(auto_mode_)\r
+ {\r
+ auto in_mode = get_mode(*video_frame);\r
+ display_mode_ = get_display_mode(in_mode, in_fps_, format_desc_.mode, format_desc_.fps);\r
\r
- if(display_mode_ == display_mode::simple && in_mode != core::video_mode::progressive && format_desc_.mode != core::video_mode::progressive && video_frame->height != static_cast<int>(format_desc_.height))\r
- display_mode_ = display_mode::deinterlace_bob_reinterlace; // The frame will most likely be scaled, we need to deinterlace->reinterlace \r
- }\r
- \r
- std::vector<safe_ptr<core::write_frame>> frames;\r
-\r
- if(display_mode_ == display_mode::deinterlace)\r
- {\r
- if(!filter_)\r
- filter_.reset(new filter(L"YADIF=0:-1"));\r
-\r
- BOOST_FOREACH(auto& frame, filter_->execute(video_frame))\r
- frames.push_back(make_write_frame(this, frame, frame_factory_));\r
-\r
+ if(display_mode_ == display_mode::simple && in_mode != core::video_mode::progressive && format_desc_.mode != core::video_mode::progressive && video_frame->height != static_cast<int>(format_desc_.height))\r
+ display_mode_ = display_mode::deinterlace_bob_reinterlace; // The frame will most likely be scaled, we need to deinterlace->reinterlace \r
+ \r
+ if(display_mode_ == display_mode::deinterlace)\r
+ filter_ = filter(L"YADIF=0:-1");\r
+ else if(display_mode_ == display_mode::deinterlace_bob || display_mode_ == display_mode::deinterlace_bob_reinterlace)\r
+ filter_ = filter(L"YADIF=1:-1");\r
+ }\r
+ else\r
+ display_mode_ = display_mode::simple;\r
+\r
+ CASPAR_LOG(info) << "frame_muxer: " << display_mode::print(display_mode_);\r
}\r
- else if(display_mode_ == display_mode::deinterlace_bob || display_mode_ == display_mode::deinterlace_bob_reinterlace)\r
+ \r
+ BOOST_FOREACH(auto& av_frame, filter_.execute(video_frame))\r
{\r
- if(!filter_)\r
- filter_.reset(new filter(L"YADIF=1:-1"));\r
+ auto frame = make_write_frame(this, av_frame, frame_factory_);\r
\r
- BOOST_FOREACH(auto& frame, filter_->execute(video_frame))\r
- frames.push_back(make_write_frame(this, frame, frame_factory_));\r
- }\r
- else\r
- frames.push_back(make_write_frame(this, make_safe(video_frame), frame_factory_));\r
-\r
- BOOST_FOREACH(auto& frame, frames)\r
- {\r
// Fix field-order if needed\r
if(frame->get_type() == core::video_mode::lower && format_desc_.mode == core::video_mode::upper)\r
frame->get_image_transform().set_fill_translation(0.0f, 0.5/static_cast<double>(frame->get_pixel_format_desc().planes[0].height));\r
video_streams_.back().push(frame);\r
++video_frame_count_;\r
\r
- process(frame_buffer_);\r
+ put_frames(frame_buffer_);\r
}\r
}\r
\r
audio_sample_count_ += audio_samples->size();\r
\r
boost::range::push_back(audio_streams_.back(), *audio_samples);\r
- process(frame_buffer_);\r
+ put_frames(frame_buffer_);\r
}\r
\r
safe_ptr<basic_frame> pop()\r
return audio_streams_.back().size() / format_desc_.audio_samples_per_frame;\r
}\r
\r
- void process(std::deque<safe_ptr<basic_frame>>& dest)\r
+ void put_frames(std::deque<safe_ptr<basic_frame>>& dest)\r
{\r
if(video_streams_.size() > 1 && audio_streams_.size() > 1 &&\r
(video_streams_.front().empty() || audio_streams_.front().empty()))\r
}\r
};\r
\r
-frame_muxer::frame_muxer(double in_fps, const video_format_desc& format_desc, const safe_ptr<core::frame_factory>& frame_factory)\r
- : impl_(new implementation(in_fps, format_desc, frame_factory)){}\r
+frame_muxer::frame_muxer(double in_fps, const safe_ptr<core::frame_factory>& frame_factory)\r
+ : impl_(new implementation(in_fps, frame_factory)){}\r
void frame_muxer::push(const std::shared_ptr<AVFrame>& video_frame){impl_->push(video_frame);}\r
void frame_muxer::push(const std::shared_ptr<std::vector<int16_t>>& audio_samples){return impl_->push(audio_samples);}\r
safe_ptr<basic_frame> frame_muxer::pop(){return impl_->pop();}\r
class frame_muxer : boost::noncopyable\r
{\r
public:\r
- frame_muxer(double in_fps, const core::video_format_desc& format_desc, const safe_ptr<core::frame_factory>& frame_factory);\r
+ frame_muxer(double in_fps, const safe_ptr<core::frame_factory>& frame_factory);\r
\r
void push(const std::shared_ptr<AVFrame>& video_frame);\r
void push(const std::shared_ptr<std::vector<int16_t>>& audio_samples);\r
av_init_packet(read_packet.get());\r
\r
const int ret = av_read_frame(format_context_.get(), read_packet.get()); // read_packet is only valid until next call of av_read_frame.\r
- if(is_eof(ret)) // Use av_dup_packet to extend its life.\r
+ if(is_eof(ret)) // Use av_dup_packet to extend its life.\r
{\r
if(loop_)\r
{\r
}\r
else\r
{ \r
- av_dup_packet(read_packet.get());\r
+ const int ret = av_dup_packet(read_packet.get());\r
+ if(ret < 0)\r
+ {\r
+ BOOST_THROW_EXCEPTION(\r
+ invalid_operation() <<\r
+ msg_info(av_error_str(ret)) <<\r
+ source_info(narrow(print())) << \r
+ boost::errinfo_api_function("av_dup_packet") <<\r
+ boost::errinfo_errno(AVUNERROR(ret)));\r
+ }\r
\r
// Make sure that the packet is correctly deallocated even if size and data is modified during decoding.\r
auto size = read_packet->size;\r
auto data = read_packet->data;\r
\r
- read_packet = std::shared_ptr<AVPacket>(read_packet.get(), [=](AVPacket* pkt)\r
+ read_packet = std::shared_ptr<AVPacket>(read_packet.get(), [=](AVPacket*)\r
{\r
read_packet->size = size;\r
read_packet->data = data;\r
, fps_(frame_factory_->get_video_format_desc().fps)\r
, nb_frames_(0)\r
{\r
- AVCodec* dec;\r
- index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);\r
+ try\r
+ {\r
+ AVCodec* dec;\r
+ index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);\r
\r
- if(index_ < 0)\r
- return;\r
- \r
- int errn = tbb_avcodec_open(context->streams[index_]->codec, dec);\r
- if(errn < 0)\r
+ if(index_ < 0)\r
+ {\r
+ BOOST_THROW_EXCEPTION(\r
+ file_read_error() <<\r
+ msg_info(av_error_str(index_)) <<\r
+ boost::errinfo_api_function("av_find_best_stream") <<\r
+ boost::errinfo_errno(AVUNERROR(index_)));\r
+ }\r
+\r
+ const int ret = tbb_avcodec_open(context->streams[index_]->codec, dec);\r
+ if(ret < 0)\r
+ { \r
+ BOOST_THROW_EXCEPTION(\r
+ file_read_error() <<\r
+ msg_info(av_error_str(ret)) <<\r
+ boost::errinfo_api_function("tbb_avcodec_open") <<\r
+ boost::errinfo_errno(AVUNERROR(ret)));\r
+ }\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ CASPAR_LOG(warning) << "[video_decoder] Failed to open video. Running without audio.";\r
return;\r
- \r
+ }\r
+ \r
codec_context_.reset(context->streams[index_]->codec, tbb_avcodec_close);\r
\r
// Some files give an invalid time_base numerator, try to fix it.\r