void FFMS_AudioSource::CacheBlock(CacheIterator &pos) { // If the previous block has the same Start sample as this one, then // we got multiple frames of audio out of a single package and should // combine them auto block = pos; if (pos == Cache.begin() || (--block)->Start != CurrentSample) block = Cache.insert(pos, AudioBlock(CurrentSample)); block->Samples += DecodeFrame->nb_samples; if (NeedsResample) ResampleAndCache(block); else { const uint8_t *data = DecodeFrame->extended_data[0]; block->Data.insert(block->Data.end(), data, data + DecodeFrame->nb_samples * BytesPerSample); } if (Cache.size() >= MaxCacheBlocks) { // Kill the oldest one auto min = CacheNoDelete; // Never drop the first one as the first packet decoded after a seek // is often decoded incorrectly and we can't seek to before the first one ++min; for (auto it = min; it != Cache.end(); ++it) if (it->Age < min->Age) min = it; if (min == pos) ++pos; Cache.erase(min); } }
void FFMS_AudioSource::CacheBlock(CacheIterator &pos) { if (NeedsResample) ResampleAndCache(pos); else Cache.insert(pos, AudioBlock(CurrentSample, DecodeFrame->nb_samples, DecodeFrame->extended_data[0], DecodeFrame->nb_samples * BytesPerSample)); if (Cache.size() >= MaxCacheBlocks) { // Kill the oldest one CacheIterator min = CacheNoDelete; // Never drop the first one as the first packet decoded after a seek // is often decoded incorrectly and we can't seek to before the first one ++min; for (CacheIterator it = min; it != Cache.end(); ++it) if (it->Age < min->Age) min = it; if (min == pos) ++pos; Cache.erase(min); } }
void FFMS_AudioSource::ResampleAndCache(CacheIterator pos) { AudioBlock& block = *Cache.insert(pos, AudioBlock(CurrentSample, DecodeFrame->nb_samples)); block.Data.reserve(DecodeFrame->nb_samples * BytesPerSample); #ifdef WITH_AVRESAMPLE block.Data.resize(block.Data.capacity()); uint8_t *OutPlanes[1] = { static_cast<uint8_t *>(&block.Data[0]) }; avresample_convert(ResampleContext, OutPlanes, block.Data.size(), DecodeFrame->nb_samples, DecodeFrame->extended_data, DecodeFrame->nb_samples * av_get_bytes_per_sample(CodecContext->sample_fmt), DecodeFrame->nb_samples); #else int width = av_get_bytes_per_sample(CodecContext->sample_fmt); uint8_t **Data = DecodeFrame->extended_data; for (int s = 0; s < DecodeFrame->nb_samples; ++s) { for (int c = 0; c < CodecContext->channels; ++c) block.Data.insert(block.Data.end(), &Data[c][s * width], &Data[c][(s + 1) * width]); } #endif }