if(!codec_context_)\r
result.push_back(std::vector<int16_t>(format_desc_.audio_samples_per_frame, 0));\r
else if(!packets_.empty())\r
- {\r
- decode();\r
+ { \r
+ if(packets_.front()) \r
+ {\r
+ AVPacket pkt;\r
+ av_init_packet(&pkt);\r
+ pkt.data = packets_.front()->data;\r
+ pkt.size = packets_.front()->size;\r
+\r
+ for(int n = 0; n < 64 && pkt.size > 0; ++n)\r
+ decode(pkt);\r
+ }\r
+ else\r
+ flush();\r
+\r
+ packets_.pop();\r
\r
while(audio_samples_.size() > format_desc_.audio_samples_per_frame)\r
{\r
return result;\r
}\r
\r
- void decode()\r
- { \r
- if(packets_.empty())\r
- return;\r
-\r
- if(!packets_.front()) // eof\r
- {\r
- packets_.pop();\r
+ void decode(AVPacket& pkt)\r
+ { \r
+ buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
+ int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE;\r
\r
- auto truncate = audio_samples_.size() % format_desc_.audio_samples_per_frame;\r
- if(truncate > 0)\r
- {\r
- audio_samples_.resize(audio_samples_.size() - truncate); \r
- CASPAR_LOG(info) << L"Truncating " << truncate << L" audio-samples."; \r
- }\r
- avcodec_flush_buffers(codec_context_.get());\r
+ const int ret = avcodec_decode_audio3(codec_context_.get(), reinterpret_cast<int16_t*>(buffer1_.data()), &written_bytes, &pkt);\r
+ if(ret < 0)\r
+ { \r
+ BOOST_THROW_EXCEPTION(\r
+ invalid_operation() <<\r
+ boost::errinfo_api_function("avcodec_decode_audio2") <<\r
+ boost::errinfo_errno(AVUNERROR(ret)));\r
}\r
- else\r
- {\r
- buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
- int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE;\r
-\r
- const int ret = avcodec_decode_audio3(codec_context_.get(), reinterpret_cast<int16_t*>(buffer1_.data()), &written_bytes, packets_.front().get());\r
- if(ret < 0)\r
- { \r
- BOOST_THROW_EXCEPTION(\r
- invalid_operation() <<\r
- boost::errinfo_api_function("avcodec_decode_audio2") <<\r
- boost::errinfo_errno(AVUNERROR(ret)));\r
- }\r
-\r
- packets_.front()->size -= ret;\r
- packets_.front()->data += ret;\r
\r
- if(packets_.front()->size <= 0)\r
- packets_.pop();\r
+ pkt.size -= ret;\r
+ pkt.data += ret;\r
+ \r
+ buffer1_.resize(written_bytes);\r
\r
- buffer1_.resize(written_bytes);\r
+ if(resampler_)\r
+ {\r
+ buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
+ auto ret = audio_resample(resampler_.get(),\r
+ reinterpret_cast<short*>(buffer2_.data()), \r
+ reinterpret_cast<short*>(buffer1_.data()), \r
+ buffer1_.size() / (av_get_bytes_per_sample(codec_context_->sample_fmt) * codec_context_->channels)); \r
+ buffer2_.resize(ret * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * format_desc_.audio_channels);\r
+ std::swap(buffer1_, buffer2_);\r
+ }\r
\r
- if(resampler_)\r
- {\r
- buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
- auto ret = audio_resample(resampler_.get(),\r
- reinterpret_cast<short*>(buffer2_.data()), \r
- reinterpret_cast<short*>(buffer1_.data()), \r
- buffer1_.size() / (av_get_bytes_per_sample(codec_context_->sample_fmt) * codec_context_->channels)); \r
- buffer2_.resize(ret * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * format_desc_.audio_channels);\r
- std::swap(buffer1_, buffer2_);\r
- }\r
+ const auto n_samples = buffer1_.size() / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);\r
+ const auto samples = reinterpret_cast<int16_t*>(buffer1_.data());\r
\r
- const auto n_samples = buffer1_.size() / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);\r
- const auto samples = reinterpret_cast<int16_t*>(buffer1_.data());\r
+ audio_samples_.insert(audio_samples_.end(), samples, samples + n_samples);\r
+ }\r
\r
- audio_samples_.insert(audio_samples_.end(), samples, samples + n_samples); \r
+ void flush()\r
+ {\r
+ auto truncate = audio_samples_.size() % format_desc_.audio_samples_per_frame;\r
+ if(truncate > 0)\r
+ {\r
+ audio_samples_.resize(audio_samples_.size() - truncate); \r
+ CASPAR_LOG(info) << L"Truncating " << truncate << L" audio-samples."; \r
}\r
+ avcodec_flush_buffers(codec_context_.get());\r
}\r
\r
bool ready() const\r
result.push_back(make_safe<core::write_frame>(reinterpret_cast<int>(this)));\r
else if(!packet_buffer_.empty())\r
{\r
- std::vector<std::shared_ptr<AVFrame>> av_frames;\r
+ std::vector<safe_ptr<AVFrame>> av_frames;\r
\r
auto packet = std::move(packet_buffer_.front());\r
packet_buffer_.pop();\r
\r
- if(!packet) // eof\r
- { \r
- if(codec_context_->codec->capabilities | CODEC_CAP_DELAY)\r
- {\r
- // FIXME: This might cause bad performance.\r
- AVPacket pkt = {0};\r
- av_frames.push_back(decode_frame(pkt));\r
- }\r
-\r
- avcodec_flush_buffers(codec_context_.get());\r
- }\r
+ if(packet) // eof\r
+ decode(*packet, av_frames); \r
else\r
- {\r
- av_frames.push_back(decode_frame(*packet)); \r
- }\r
+ flush(av_frames);\r
\r
if(filter_)\r
{\r
\r
filter_tasks_.wait();\r
\r
- boost::range::push_back(av_frames, filter_->poll());\r
+ av_frames = filter_->poll();\r
\r
filter_tasks_.run([=]\r
{\r
}\r
\r
BOOST_FOREACH(auto& frame, av_frames)\r
- result.push_back(make_write_frame(this, make_safe(frame), frame_factory_));\r
+ result.push_back(make_write_frame(this, frame, frame_factory_));\r
}\r
\r
return result;\r
}\r
\r
- std::shared_ptr<AVFrame> decode_frame(AVPacket& packet)\r
+ void decode(AVPacket& packet, std::vector<safe_ptr<AVFrame>>& av_frames)\r
{\r
std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
\r
boost::errinfo_errno(AVUNERROR(errn)));\r
}\r
\r
- if(frame_finished == 0) \r
- decoded_frame.reset();\r
+ if(frame_finished != 0) \r
+ av_frames.push_back(make_safe(decoded_frame));\r
+ }\r
+\r
+ void flush(std::vector<safe_ptr<AVFrame>>& av_frames)\r
+ {\r
+ if(codec_context_->codec->capabilities | CODEC_CAP_DELAY)\r
+ {\r
+ // FIXME: This might cause bad performance.\r
+ AVPacket pkt = {0};\r
+ decode(pkt, av_frames);\r
+ }\r
\r
- return decoded_frame;\r
+ avcodec_flush_buffers(codec_context_.get());\r
}\r
\r
bool ready() const\r