explicit implementation(AVCodecContext* codec_context, double fps) \r
: codec_context_(codec_context)\r
, audio_buffer_(4*SAMPLE_RATE*2+FF_INPUT_BUFFER_PADDING_SIZE/2)\r
- , audio_frame_size_(static_cast<size_t>(static_cast<double>(SAMPLE_RATE) / fps) * N_CHANNELS){}\r
+ , audio_frame_size_(static_cast<size_t>(static_cast<double>(SAMPLE_RATE) / fps) * N_CHANNELS)\r
+ {\r
+ if(!codec_context)\r
+ BOOST_THROW_EXCEPTION(null_argument() << arg_name_info("codec_context")); \r
+ }\r
\r
std::vector<std::vector<short>> execute(const aligned_buffer& audio_packet)\r
{ \r
const int result = avcodec_decode_audio2(codec_context_, audio_buffer_.data(), &written_bytes, audio_packet.data(), audio_packet.size());\r
\r
if(result <= 0 || codec_context_->sample_rate != SAMPLE_RATE || codec_context_->channels != 2)\r
- return std::vector<std::vector<short>>();\r
+ BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Invalid audio stream"));\r
\r
current_chunk_.insert(current_chunk_.end(), audio_buffer_.data(), audio_buffer_.data() + written_bytes/2);\r
\r
\r
#include <tbb/parallel_invoke.h>\r
\r
+#include <boost/optional.hpp>\r
+\r
#include <deque>\r
\r
using namespace boost::assign;\r
struct ffmpeg_producer : public frame_producer\r
{\r
input input_; \r
- audio_decoder audio_decoder_;\r
+ std::unique_ptr<audio_decoder> audio_decoder_;\r
video_decoder video_decoder_;\r
\r
std::deque<safe_ptr<write_frame>> video_frame_channel_; \r
: filename_(filename)\r
, last_frame_(draw_frame(draw_frame::empty()))\r
, input_(filename)\r
- , video_decoder_(input_.get_video_codec_context().get())\r
- , audio_decoder_(input_.get_audio_codec_context().get(), input_.fps())\r
- { \r
+ , video_decoder_(input_.get_video_codec_context().get()) \r
+ { \r
input_.set_loop(std::find(params.begin(), params.end(), L"LOOP") != params.end());\r
\r
+ if(input_.get_audio_codec_context().get())\r
+ audio_decoder_.reset(new audio_decoder(input_.get_audio_codec_context().get(), input_.fps()));\r
+\r
auto seek = std::find(params.begin(), params.end(), L"SEEK");\r
if(seek != params.end() && ++seek != params.end())\r
{\r
}, \r
[&] \r
{ // Audio Decoding\r
- if(!audio_packet.empty())\r
+ if(!audio_packet.empty() && audio_decoder_)\r
{\r
- auto chunks = audio_decoder_.execute(audio_packet);\r
- audio_chunk_channel_.insert(audio_chunk_channel_.end(), chunks.begin(), chunks.end());\r
+ try\r
+ {\r
+ auto chunks = audio_decoder_->execute(audio_packet);\r
+ audio_chunk_channel_.insert(audio_chunk_channel_.end(), chunks.begin(), chunks.end());\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ audio_decoder_.reset();\r
+ }\r
}\r
});\r
\r
- while(!video_frame_channel_.empty() && (!audio_chunk_channel_.empty() || input_.get_audio_codec_context() == nullptr))\r
+ while(!video_frame_channel_.empty() && (!audio_chunk_channel_.empty() || !audio_decoder_))\r
{\r
- if(input_.get_audio_codec_context() != nullptr) \r
+ if(audio_decoder_) \r
{\r
video_frame_channel_.front()->audio_data() = std::move(audio_chunk_channel_.front());\r
audio_chunk_channel_.pop_front();\r