std::shared_ptr<AVCodecContext> codec_context_; \r
const core::video_format_desc format_desc_;\r
int index_;\r
- std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>> buffer_; // avcodec_decode_audio3 needs 4 byte alignment\r
+ std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> buffer1_; // avcodec_decode_audio3 needs 4 byte alignment\r
+ std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> buffer2_; // avcodec_decode_audio3 needs 4 byte alignment\r
std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>> audio_samples_; // avcodec_decode_audio3 needs 4 byte alignment\r
std::queue<std::shared_ptr<AVPacket>> packets_;\r
+ std::shared_ptr<ReSampleContext> resampler_;\r
public:\r
explicit implementation(const std::shared_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc) \r
: format_desc_(format_desc) \r
- {\r
+ { \r
AVCodec* dec;\r
index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);\r
\r
\r
if(codec_context_ &&\r
(codec_context_->sample_rate != static_cast<int>(format_desc_.audio_sample_rate) || \r
- codec_context_->channels != static_cast<int>(format_desc_.audio_channels)))\r
+ codec_context_->channels != static_cast<int>(format_desc_.audio_channels)) ||\r
+ codec_context_->sample_fmt != AV_SAMPLE_FMT_S16)\r
{ \r
- BOOST_THROW_EXCEPTION(\r
- file_read_error() <<\r
- msg_info("Invalid sample-rate or number of channels.") <<\r
- arg_value_info(boost::lexical_cast<std::string>(codec_context_->sample_rate)) << \r
- arg_name_info("codec_context"));\r
+ auto resampler = av_audio_resample_init(format_desc_.audio_channels, codec_context_->channels,
+ format_desc_.audio_sample_rate, codec_context_->sample_rate,
+ AV_SAMPLE_FMT_S16, codec_context_->sample_fmt,
+ 16, 10, 0, 0.8);\r
+\r
+ CASPAR_LOG(warning) << L" Invalid audio format.";\r
+\r
+ if(resampler)\r
+ resampler_.reset(resampler, audio_resample_close);\r
+ else\r
+ codec_context_ = nullptr;\r
} \r
}\r
\r
}\r
else\r
{\r
- buffer_.resize(4*format_desc_.audio_sample_rate*2+FF_INPUT_BUFFER_PADDING_SIZE/2, 0);\r
-\r
- int written_bytes = buffer_.size() - FF_INPUT_BUFFER_PADDING_SIZE/2;\r
- const int errn = avcodec_decode_audio3(codec_context_.get(), buffer_.data(), &written_bytes, packet.get());\r
+ buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
+ int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE;\r
+ // TODO: Packet might contain multiple frames\r
+ const int errn = avcodec_decode_audio3(codec_context_.get(), reinterpret_cast<int16_t*>(buffer1_.data()), &written_bytes, packet.get());\r
if(errn < 0)\r
{ \r
BOOST_THROW_EXCEPTION(\r
boost::errinfo_errno(AVUNERROR(errn)));\r
}\r
\r
- buffer_.resize(written_bytes/2);\r
- audio_samples_.insert(audio_samples_.end(), buffer_.begin(), buffer_.end());\r
- buffer_.clear(); \r
+ buffer1_.resize(written_bytes);\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)); \r
+ buffer2_.resize(ret);\r
+ std::swap(buffer1_, buffer2_);\r
+ }\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
+ audio_samples_.insert(audio_samples_.end(), samples, samples + n_samples); \r
}\r
}\r
\r